Sync test_dense_evolution.py from v8.1.35
Browse files- test_dense_evolution.py +27 -4
test_dense_evolution.py
CHANGED
|
@@ -1203,19 +1203,26 @@ class TestParserEvalSecurity:
|
|
| 1203 |
|
| 1204 |
@pytest.mark.parametrize('payload', _ESCAPE_PAYLOADS)
|
| 1205 |
def test_eval_param_blocks_sandbox_escapes(self, payload):
|
| 1206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1207 |
|
| 1208 |
@pytest.mark.parametrize('payload', _ESCAPE_PAYLOADS)
|
| 1209 |
def test_resolve_int_expr_blocks_sandbox_escapes(self, payload):
|
| 1210 |
assert QASMParser()._resolve_int_expr(payload, {}) is None
|
| 1211 |
|
| 1212 |
-
def
|
| 1213 |
# end-to-end through the actual public entry point, not just the
|
| 1214 |
# internal method directly
|
| 1215 |
qasm = ('OPENQASM 3.0; qubit[1] q; '
|
| 1216 |
'rx(().__class__.__bases__[0].__subclasses__().__len__()) q[0];')
|
| 1217 |
-
|
| 1218 |
-
|
| 1219 |
|
| 1220 |
def test_original_exploit_in_for_loop_bound_yields_no_ops(self):
|
| 1221 |
qasm = ('OPENQASM 3.0; qubit[1] q; '
|
|
@@ -1234,6 +1241,22 @@ class TestParserEvalSecurity:
|
|
| 1234 |
def test_legitimate_expressions_unchanged(self, expr, expected):
|
| 1235 |
assert QASMParser()._eval_param(expr) == pytest.approx(expected)
|
| 1236 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1237 |
def test_legitimate_for_loop_bounds_unchanged(self):
|
| 1238 |
qasm = 'qreg q[3]; int n = 3; for int i in [0:n-1] { x q[i]; }'
|
| 1239 |
circ = QASMParser().parse(qasm)
|
|
|
|
| 1203 |
|
| 1204 |
@pytest.mark.parametrize('payload', _ESCAPE_PAYLOADS)
|
| 1205 |
def test_eval_param_blocks_sandbox_escapes(self, payload):
|
| 1206 |
+
# _eval_param used to swallow every rejected expression into a
|
| 1207 |
+
# silent 0.0 (same fallback a genuine typo like 'pi * / 2' hit
|
| 1208 |
+
# too); it now raises ValueError instead -- still structurally
|
| 1209 |
+
# blocked (the AST whitelist never reaches these nodes), just
|
| 1210 |
+
# explicit about it instead of silent, same as a malformed
|
| 1211 |
+
# expression from a typo.
|
| 1212 |
+
with pytest.raises(ValueError):
|
| 1213 |
+
QASMParser()._eval_param(payload)
|
| 1214 |
|
| 1215 |
@pytest.mark.parametrize('payload', _ESCAPE_PAYLOADS)
|
| 1216 |
def test_resolve_int_expr_blocks_sandbox_escapes(self, payload):
|
| 1217 |
assert QASMParser()._resolve_int_expr(payload, {}) is None
|
| 1218 |
|
| 1219 |
+
def test_original_exploit_through_full_parse_raises(self):
|
| 1220 |
# end-to-end through the actual public entry point, not just the
|
| 1221 |
# internal method directly
|
| 1222 |
qasm = ('OPENQASM 3.0; qubit[1] q; '
|
| 1223 |
'rx(().__class__.__bases__[0].__subclasses__().__len__()) q[0];')
|
| 1224 |
+
with pytest.raises(ValueError):
|
| 1225 |
+
QASMParser().parse(qasm)
|
| 1226 |
|
| 1227 |
def test_original_exploit_in_for_loop_bound_yields_no_ops(self):
|
| 1228 |
qasm = ('OPENQASM 3.0; qubit[1] q; '
|
|
|
|
| 1241 |
def test_legitimate_expressions_unchanged(self, expr, expected):
|
| 1242 |
assert QASMParser()._eval_param(expr) == pytest.approx(expected)
|
| 1243 |
|
| 1244 |
+
@pytest.mark.parametrize('malformed', [
|
| 1245 |
+
'pi * / 2', 'pi +', '(pi', 'pi 2', '**pi', 'pi // 2',
|
| 1246 |
+
])
|
| 1247 |
+
def test_malformed_expression_raises_instead_of_silent_zero(self, malformed):
|
| 1248 |
+
# Found via an external code-review report, reproduced directly:
|
| 1249 |
+
# 'rx(pi * / 2) q[0];' used to parse successfully and silently
|
| 1250 |
+
# produce rx(0.0) -- a different, valid circuit, no signal a typo
|
| 1251 |
+
# happened. Now raises instead of hiding the mistake.
|
| 1252 |
+
with pytest.raises(ValueError):
|
| 1253 |
+
QASMParser()._eval_param(malformed)
|
| 1254 |
+
|
| 1255 |
+
def test_malformed_expression_through_full_parse_raises(self):
|
| 1256 |
+
qasm = 'OPENQASM 2.0; include "qelib1.inc"; qreg q[1]; rx(pi * / 2) q[0];'
|
| 1257 |
+
with pytest.raises(ValueError):
|
| 1258 |
+
QASMParser().parse(qasm)
|
| 1259 |
+
|
| 1260 |
def test_legitimate_for_loop_bounds_unchanged(self):
|
| 1261 |
qasm = 'qreg q[3]; int n = 3; for int i in [0:n-1] { x q[i]; }'
|
| 1262 |
circ = QASMParser().parse(qasm)
|