diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 3f180b426..68eb1c406 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -108,12 +108,15 @@ 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 (!absl::SimpleAtoi(tok, &tmp) || tmp >= num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid control qubit: " + std::string(tok)); + } control_qubits->push_back(num_qubits - tmp - 1); } control_values->reserve(control_v_toks.size()); @@ -156,8 +159,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) || q0 >= num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid 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 +191,19 @@ 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) || 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 || q0 == q1) { + return Status(absl::StatusCode::kInvalidArgument, + "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); if (!s.ok()) { @@ -207,10 +227,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) || q0 >= num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -255,11 +282,21 @@ 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) || 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 || q0 == q1) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid or duplicate qubit id: " + op.qubits(1).id()); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -394,10 +431,18 @@ 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) || q0 < 0 || + q0 >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -453,11 +498,23 @@ 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) || 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 || q0 == q1) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid or duplicate qubit id: " + op.qubits(1).id()); + } absl::optional theta_symbol; u = ParseProtoArg(op, "theta", param_map, &theta, &theta_symbol); @@ -509,11 +566,23 @@ 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) || 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 || q0 == q1) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid or duplicate qubit id: " + op.qubits(1).id()); + } absl::optional exponent_symbol; u = ParseProtoArg(op, "exponent", param_map, &exp, &exponent_symbol); @@ -599,10 +668,18 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p_x", {}, &p_x); u = ParseProtoArg(op, "p_y", {}, &p_y); @@ -620,10 +697,18 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) { @@ -637,10 +722,18 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) { @@ -660,8 +753,16 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } auto chan = qsim::Cirq::ResetChannel::Create(time, num_qubits - q - 1); ncircuit->channels.push_back(chan); @@ -672,10 +773,18 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "gamma", {}, &gamma); if (!u.ok()) { @@ -691,10 +800,18 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "gamma", {}, &gamma); if (!u.ok()) { @@ -711,10 +828,18 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) { @@ -730,10 +855,18 @@ 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) || q < 0 || + q >= (int)num_qubits) { + return Status(absl::StatusCode::kInvalidArgument, + "Invalid qubit id: " + op.qubits(0).id()); + } u = ParseProtoArg(op, "p", {}, &p); if (!u.ok()) {