From 144fd62a650269989297dd7316885ea2fca4d6b7 Mon Sep 17 00:00:00 2001 From: mhucka Date: Fri, 22 May 2026 18:50:57 +0000 Subject: [PATCH 1/5] Add validation logic on user-provided inputs --- .../core/src/circuit_parser_qsim.cc | 175 ++++++++++++++---- 1 file changed, 140 insertions(+), 35 deletions(-) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 3f180b426..a6a611cbb 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -108,12 +108,16 @@ inline Status ParseProtoControls(const Operation& op, return ::tensorflow::Status(); } bool valid; - unsigned int tmp; + unsigned int tmp = 0; control_qubits->reserve(control_toks.size()); for (auto tok : control_toks) { // don't bother error checking since this is done earlier // in program_resolution. valid = absl::SimpleAtoi(tok, &tmp); + if (!valid) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable control qubit."); + } control_qubits->push_back(num_qubits - tmp - 1); } control_values->reserve(control_v_toks.size()); @@ -156,8 +160,15 @@ inline Status SingleConstantGate( const std::function& create_f, const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { - unsigned int q0; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q0); + unsigned int q0 = 0; + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } auto gate = create_f(time, num_qubits - q0 - 1); Status s = OptionalInsertControls(op, num_qubits, &gate); if (!s.ok()) { @@ -181,9 +192,15 @@ inline Status TwoConstantGate( create_f, const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { - unsigned int q0, q1; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q0); - (void)absl::SimpleAtoi(op.qubits(1).id(), &q1); + unsigned int q0 = 0, q1 = 0; + if (op.qubits_size() < 2) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id."); + } auto gate = create_f(time, num_qubits - q0 - 1, num_qubits - q1 - 1); Status s = OptionalInsertControls(op, num_qubits, &gate); if (!s.ok()) { @@ -207,10 +224,17 @@ inline Status SingleEigenGate( create_f, const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { - unsigned int q0; + unsigned int q0 = 0; float exp, exp_s, gs; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q0); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -255,11 +279,17 @@ inline Status TwoEigenGate( float, float)>& create_f, const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { - unsigned int q0, q1; + unsigned int q0 = 0, q1 = 0; float exp, exp_s, gs; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q0); - (void)absl::SimpleAtoi(op.qubits(1).id(), &q1); + if (op.qubits_size() < 2) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id."); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -394,10 +424,17 @@ inline Status PhasedXGate(const Operation& op, const SymbolMap& param_map, const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { - int q0; + int q0 = 0; float pexp, pexp_s, exp, exp_s, gs; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q0); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -453,11 +490,17 @@ inline Status FsimGate(const Operation& op, const SymbolMap& param_map, const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { - int q0, q1; + int q0 = 0, q1 = 0; float theta, theta_s, phi, phi_s; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q0); - (void)absl::SimpleAtoi(op.qubits(1).id(), &q1); + if (op.qubits_size() < 2) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id."); + } absl::optional theta_symbol; u = ParseProtoArg(op, "theta", param_map, &theta, &theta_symbol); @@ -509,11 +552,17 @@ inline Status PhasedISwapGate(const Operation& op, const SymbolMap& param_map, const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { - int q0, q1; + int q0 = 0, q1 = 0; float pexp, pexp_s, exp, exp_s; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q0); - (void)absl::SimpleAtoi(op.qubits(1).id(), &q1); + if (op.qubits_size() < 2) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id."); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -599,10 +648,17 @@ inline Status AsymmetricDepolarizingChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; + int q = 0; float p_x, p_y, p_z; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p_x", {}, &p_x); u = ParseProtoArg(op, "p_y", {}, &p_y); @@ -620,10 +676,17 @@ inline Status DepolarizingChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; + int q = 0; float p; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) { @@ -637,10 +700,17 @@ inline Status DepolarizingChannel(const Operation& op, inline Status GADChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; + int q = 0; float p, gamma; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) { @@ -660,8 +730,15 @@ inline Status GADChannel(const Operation& op, const unsigned int num_qubits, inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + int q = 0; + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } auto chan = qsim::Cirq::ResetChannel::Create(time, num_qubits - q - 1); ncircuit->channels.push_back(chan); @@ -672,10 +749,17 @@ inline Status AmplitudeDampingChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; + int q = 0; float gamma; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "gamma", {}, &gamma); if (!u.ok()) { @@ -691,10 +775,17 @@ inline Status PhaseDampingChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; + int q = 0; float gamma; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "gamma", {}, &gamma); if (!u.ok()) { @@ -711,10 +802,17 @@ inline Status PhaseFlipChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; + int q = 0; float p; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) { @@ -730,10 +828,17 @@ inline Status PhaseFlipChannel(const Operation& op, inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { - int q; + int q = 0; float p; Status u; - (void)absl::SimpleAtoi(op.qubits(0).id(), &q); + if (op.qubits_size() < 1) { + return Status(absl::StatusCode::kInvalidArgument, + "Missing qubit(s) in gate."); + } + if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + return Status(absl::StatusCode::kInvalidArgument, + "Unparseable qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) { From e51ad395fd17760d5b5e22302ac46ef5eef726d2 Mon Sep 17 00:00:00 2001 From: mhucka Date: Fri, 22 May 2026 19:28:19 +0000 Subject: [PATCH 2/5] Add additional checks --- .../core/src/circuit_parser_qsim.cc | 77 +++++++++++-------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index a6a611cbb..6cebcbe08 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -113,10 +113,9 @@ inline Status ParseProtoControls(const Operation& op, for (auto tok : control_toks) { // don't bother error checking since this is done earlier // in program_resolution. - valid = absl::SimpleAtoi(tok, &tmp); - if (!valid) { + if (!absl::SimpleAtoi(tok, &tmp) || tmp >= num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable control qubit."); + "Invalid control qubit: " + std::string(tok)); } control_qubits->push_back(num_qubits - tmp - 1); } @@ -165,9 +164,9 @@ inline Status SingleConstantGate( return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 >= num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } auto gate = create_f(time, num_qubits - q0 - 1); Status s = OptionalInsertControls(op, num_qubits, &gate); @@ -197,9 +196,13 @@ inline Status TwoConstantGate( return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 >= num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 >= num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id."); + "Invalid qubit id: " + op.qubits(1).id()); } auto gate = create_f(time, num_qubits - q0 - 1, num_qubits - q1 - 1); Status s = OptionalInsertControls(op, num_qubits, &gate); @@ -286,9 +289,13 @@ inline Status TwoEigenGate( return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 >= num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id."); + "Invalid qubit id: " + op.qubits(0).id()); + } + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 >= num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(1).id()); } absl::optional exponent_symbol; @@ -431,9 +438,9 @@ inline Status PhasedXGate(const Operation& op, const SymbolMap& param_map, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || q0 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } absl::optional exponent_symbol; @@ -497,9 +504,13 @@ inline Status FsimGate(const Operation& op, const SymbolMap& param_map, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || q0 >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || q1 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id."); + "Invalid qubit id: " + op.qubits(1).id()); } absl::optional theta_symbol; @@ -559,9 +570,13 @@ inline Status PhasedISwapGate(const Operation& op, const SymbolMap& param_map, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || !absl::SimpleAtoi(op.qubits(1).id(), &q1)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || q0 >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || q1 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id."); + "Invalid qubit id: " + op.qubits(1).id()); } absl::optional exponent_symbol; @@ -655,9 +670,9 @@ inline Status AsymmetricDepolarizingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } u = ParseProtoArg(op, "p_x", {}, &p_x); @@ -683,9 +698,9 @@ inline Status DepolarizingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } u = ParseProtoArg(op, "p", {}, &p); @@ -707,9 +722,9 @@ inline Status GADChannel(const Operation& op, const unsigned int num_qubits, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } u = ParseProtoArg(op, "p", {}, &p); @@ -735,9 +750,9 @@ inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } auto chan = qsim::Cirq::ResetChannel::Create(time, num_qubits - q - 1); @@ -756,9 +771,9 @@ inline Status AmplitudeDampingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } u = ParseProtoArg(op, "gamma", {}, &gamma); @@ -782,9 +797,9 @@ inline Status PhaseDampingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } u = ParseProtoArg(op, "gamma", {}, &gamma); @@ -809,9 +824,9 @@ inline Status PhaseFlipChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } u = ParseProtoArg(op, "p", {}, &p); @@ -835,9 +850,9 @@ inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } u = ParseProtoArg(op, "p", {}, &p); From 73920bd04393992dfcffdbe5be9877e0ab68bcc3 Mon Sep 17 00:00:00 2001 From: mhucka Date: Fri, 22 May 2026 19:29:50 +0000 Subject: [PATCH 3/5] Format --- .../core/src/circuit_parser_qsim.cc | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 6cebcbe08..bb9777dec 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -438,7 +438,8 @@ inline Status PhasedXGate(const Operation& op, const SymbolMap& param_map, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || q0 >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || + q0 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -504,11 +505,13 @@ inline Status FsimGate(const Operation& op, const SymbolMap& param_map, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || q0 >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || + q0 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } - if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || q1 >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || + q1 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(1).id()); } @@ -570,11 +573,13 @@ inline Status PhasedISwapGate(const Operation& op, const SymbolMap& param_map, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || q0 >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 < 0 || + q0 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } - if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || q1 >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || + q1 >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(1).id()); } @@ -670,7 +675,8 @@ inline Status AsymmetricDepolarizingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -698,7 +704,8 @@ inline Status DepolarizingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -722,7 +729,8 @@ inline Status GADChannel(const Operation& op, const unsigned int num_qubits, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -750,7 +758,8 @@ inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -771,7 +780,8 @@ inline Status AmplitudeDampingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -797,7 +807,8 @@ inline Status PhaseDampingChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -824,7 +835,8 @@ inline Status PhaseFlipChannel(const Operation& op, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } @@ -850,7 +862,8 @@ inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || q >= (int)num_qubits) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q) || q < 0 || + q >= (int)num_qubits) { return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } From ad4dea113a171cec2dddf4c5363e9692ea68c0dc Mon Sep 17 00:00:00 2001 From: mhucka Date: Fri, 22 May 2026 19:43:20 +0000 Subject: [PATCH 4/5] Add another check --- tensorflow_quantum/core/src/circuit_parser_qsim.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index bb9777dec..3bf1811aa 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -234,9 +234,9 @@ inline Status SingleEigenGate( return Status(absl::StatusCode::kInvalidArgument, "Missing qubit(s) in gate."); } - if (!absl::SimpleAtoi(op.qubits(0).id(), &q0)) { + if (!absl::SimpleAtoi(op.qubits(0).id(), &q0) || q0 >= num_qubits) { return Status(absl::StatusCode::kInvalidArgument, - "Unparseable qubit id: " + op.qubits(0).id()); + "Invalid qubit id: " + op.qubits(0).id()); } absl::optional exponent_symbol; From bac9c0589b6895d6817e463633d4cd4b09ff6f16 Mon Sep 17 00:00:00 2001 From: mhucka Date: Fri, 22 May 2026 20:08:50 +0000 Subject: [PATCH 5/5] Check that qubits are distinct --- .../core/src/circuit_parser_qsim.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 3bf1811aa..68eb1c406 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -200,9 +200,9 @@ inline Status TwoConstantGate( return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } - if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 >= num_qubits) { + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 >= num_qubits || q0 == q1) { return Status(absl::StatusCode::kInvalidArgument, - "Invalid qubit id: " + op.qubits(1).id()); + "Invalid or duplicate qubit id: " + op.qubits(1).id()); } auto gate = create_f(time, num_qubits - q0 - 1, num_qubits - q1 - 1); Status s = OptionalInsertControls(op, num_qubits, &gate); @@ -293,9 +293,9 @@ inline Status TwoEigenGate( return Status(absl::StatusCode::kInvalidArgument, "Invalid qubit id: " + op.qubits(0).id()); } - if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 >= num_qubits) { + if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 >= num_qubits || q0 == q1) { return Status(absl::StatusCode::kInvalidArgument, - "Invalid qubit id: " + op.qubits(1).id()); + "Invalid or duplicate qubit id: " + op.qubits(1).id()); } absl::optional exponent_symbol; @@ -511,9 +511,9 @@ inline Status FsimGate(const Operation& op, const SymbolMap& param_map, "Invalid qubit id: " + op.qubits(0).id()); } if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || - q1 >= (int)num_qubits) { + q1 >= (int)num_qubits || q0 == q1) { return Status(absl::StatusCode::kInvalidArgument, - "Invalid qubit id: " + op.qubits(1).id()); + "Invalid or duplicate qubit id: " + op.qubits(1).id()); } absl::optional theta_symbol; @@ -579,9 +579,9 @@ inline Status PhasedISwapGate(const Operation& op, const SymbolMap& param_map, "Invalid qubit id: " + op.qubits(0).id()); } if (!absl::SimpleAtoi(op.qubits(1).id(), &q1) || q1 < 0 || - q1 >= (int)num_qubits) { + q1 >= (int)num_qubits || q0 == q1) { return Status(absl::StatusCode::kInvalidArgument, - "Invalid qubit id: " + op.qubits(1).id()); + "Invalid or duplicate qubit id: " + op.qubits(1).id()); } absl::optional exponent_symbol;