/home/mdboom/Work/builds/cpython/Python/ast.c
Line | Count | Source (jump to first uncovered line) |
1 | /* |
2 | * This file exposes PyAST_Validate interface to check the integrity |
3 | * of the given abstract syntax tree (potentially constructed manually). |
4 | */ |
5 | #include "Python.h" |
6 | #include "pycore_ast.h" // asdl_stmt_seq |
7 | #include "pycore_pystate.h" // _PyThreadState_GET() |
8 | |
9 | #include <assert.h> |
10 | #include <stdbool.h> |
11 | |
12 | struct validator { |
13 | int recursion_depth; /* current recursion depth */ |
14 | int recursion_limit; /* recursion limit */ |
15 | }; |
16 | |
17 | static int validate_stmts(struct validator *, asdl_stmt_seq *); |
18 | static int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int); |
19 | static int validate_patterns(struct validator *, asdl_pattern_seq *, int); |
20 | static int _validate_nonempty_seq(asdl_seq *, const char *, const char *); |
21 | static int validate_stmt(struct validator *, stmt_ty); |
22 | static int validate_expr(struct validator *, expr_ty, expr_context_ty); |
23 | static int validate_pattern(struct validator *, pattern_ty, int); |
24 | |
25 | #define VALIDATE_POSITIONS(node) \ |
26 | if (node->lineno > node->end_lineno) { \ |
27 | PyErr_Format(PyExc_ValueError, \ |
28 | "AST node line range (%d, %d) is not valid", \ |
29 | node->lineno, node->end_lineno); \ |
30 | return 0; \ |
31 | } \ |
32 | if (353k (353k node->lineno < 0353k && node->end_lineno != node->lineno2 ) || \ |
33 | (353k node->col_offset < 0353k && node->col_offset != node->end_col_offset3 )) { \ |
34 | PyErr_Format(PyExc_ValueError, \ |
35 | "AST node column range (%d, %d) for line range (%d, %d) is not valid", \ |
36 | node->col_offset, node->end_col_offset, node->lineno, node->end_lineno); \ |
37 | return 0; \ |
38 | } \ |
39 | if (353k node->lineno == node->end_lineno353k && node->col_offset > node->end_col_offset317k ) { \ |
40 | PyErr_Format(PyExc_ValueError, \ |
41 | "line %d, column %d-%d is not a valid range", \ |
42 | node->lineno, node->col_offset, node->end_col_offset); \ |
43 | return 0; \ |
44 | } |
45 | |
46 | static int |
47 | validate_name(PyObject *name) |
48 | { |
49 | assert(PyUnicode_Check(name)); |
50 | static const char * const forbidden[] = { |
51 | "None", |
52 | "True", |
53 | "False", |
54 | NULL |
55 | }; |
56 | for (int i = 0; forbidden[i] != NULL; i++357k ) { Branch (56:21): [True: 357k, False: 119k]
|
57 | if (_PyUnicode_EqualToASCIIString(name, forbidden[i])) { Branch (57:13): [True: 7, False: 357k]
|
58 | PyErr_Format(PyExc_ValueError, "identifier field can't represent '%s' constant", forbidden[i]); |
59 | return 0; |
60 | } |
61 | } |
62 | return 1; |
63 | } |
64 | |
65 | static int |
66 | validate_comprehension(struct validator *state, asdl_comprehension_seq *gens) |
67 | { |
68 | Py_ssize_t i; |
69 | if (!asdl_seq_LEN(gens)) { Branch (69:9): [True: 4, False: 608]
|
70 | PyErr_SetString(PyExc_ValueError, "comprehension with no generators"); |
71 | return 0; |
72 | } |
73 | for (i = 0; 608 i < asdl_seq_LEN(gens); i++619 ) { Branch (73:17): [True: 635, False: 592]
|
74 | comprehension_ty comp = asdl_seq_GET(gens, i); |
75 | if (!validate_expr(state, comp->target, Store) || Branch (75:13): [True: 4, False: 631]
|
76 | !validate_expr(state, comp->iter, Load)631 || Branch (76:13): [True: 4, False: 627]
|
77 | !validate_exprs(state, comp->ifs, Load, 0)627 ) Branch (77:13): [True: 8, False: 619]
|
78 | return 0; |
79 | } |
80 | return 1; |
81 | } |
82 | |
83 | static int |
84 | validate_keywords(struct validator *state, asdl_keyword_seq *keywords) |
85 | { |
86 | Py_ssize_t i; |
87 | for (i = 0; i < asdl_seq_LEN(keywords); i++3.30k ) Branch (87:17): [True: 3.30k, False: 30.9k]
|
88 | if (!validate_expr(state, (asdl_seq_GET(keywords, i))->value, Load)) Branch (88:13): [True: 2, False: 3.30k]
|
89 | return 0; |
90 | return 1; |
91 | } |
92 | |
93 | static int |
94 | validate_args(struct validator *state, asdl_arg_seq *args) |
95 | { |
96 | Py_ssize_t i; |
97 | for (i = 0; i < asdl_seq_LEN(args); i++14.7k ) { Branch (97:17): [True: 14.7k, False: 22.7k]
|
98 | arg_ty arg = asdl_seq_GET(args, i); |
99 | VALIDATE_POSITIONS14.7k (arg); |
100 | if (arg->annotation && !validate_expr(state, arg->annotation, Load)62 ) Branch (100:13): [True: 62, False: 14.6k]
Branch (100:32): [True: 6, False: 56]
|
101 | return 0; |
102 | } |
103 | return 1; |
104 | } |
105 | |
106 | static const char * |
107 | expr_context_name(expr_context_ty ctx) |
108 | { |
109 | switch (ctx) { Branch (109:13): [True: 0, False: 173]
|
110 | case Load: Branch (110:5): [True: 86, False: 87]
|
111 | return "Load"; |
112 | case Store: Branch (112:5): [True: 86, False: 87]
|
113 | return "Store"; |
114 | case Del: Branch (114:5): [True: 1, False: 172]
|
115 | return "Del"; |
116 | // No default case so compiler emits warning for unhandled cases |
117 | } |
118 | Py_UNREACHABLE0 (); |
119 | } |
120 | |
121 | static int |
122 | validate_arguments(struct validator *state, arguments_ty args) |
123 | { |
124 | if (!validate_args(state, args->posonlyargs) || !validate_args(state, args->args)7.60k ) { Branch (124:9): [True: 2, False: 7.60k]
Branch (124:53): [True: 2, False: 7.59k]
|
125 | return 0; |
126 | } |
127 | if (args->vararg && args->vararg->annotation283 Branch (127:9): [True: 283, False: 7.31k]
Branch (127:25): [True: 10, False: 273]
|
128 | && !validate_expr(state, args->vararg->annotation, Load)10 ) { Branch (128:12): [True: 0, False: 10]
|
129 | return 0; |
130 | } |
131 | if (!validate_args(state, args->kwonlyargs)) Branch (131:9): [True: 2, False: 7.59k]
|
132 | return 0; |
133 | if (args->kwarg && args->kwarg->annotation173 Branch (133:9): [True: 173, False: 7.42k]
Branch (133:24): [True: 4, False: 169]
|
134 | && !validate_expr(state, args->kwarg->annotation, Load)4 ) { Branch (134:12): [True: 0, False: 4]
|
135 | return 0; |
136 | } |
137 | if (asdl_seq_LEN(args->defaults) > asdl_seq_LEN(args->posonlyargs) + asdl_seq_LEN(args->args)) { Branch (137:9): [True: 2, False: 7.59k]
|
138 | PyErr_SetString(PyExc_ValueError, "more positional defaults than args on arguments"); |
139 | return 0; |
140 | } |
141 | if (asdl_seq_LEN(args->kw_defaults) != asdl_seq_LEN(args->kwonlyargs)) { Branch (141:9): [True: 2, False: 7.59k]
|
142 | PyErr_SetString(PyExc_ValueError, "length of kwonlyargs is not the same as " |
143 | "kw_defaults on arguments"); |
144 | return 0; |
145 | } |
146 | return validate_exprs(state, args->defaults, Load, 0) && validate_exprs(state, args->kw_defaults, Load, 1)7.59k ; Branch (146:12): [True: 7.59k, False: 2]
Branch (146:62): [True: 7.58k, False: 2]
|
147 | } |
148 | |
149 | static int |
150 | validate_constant(struct validator *state, PyObject *value) |
151 | { |
152 | if (value == Py_None || value == 41.8k Py_Ellipsis41.8k ) Branch (152:9): [True: 4.84k, False: 41.8k]
Branch (152:29): [True: 51, False: 41.7k]
|
153 | return 1; |
154 | |
155 | if (PyLong_CheckExact(value) |
156 | || PyFloat_CheckExact(value) |
157 | || PyComplex_CheckExact(value) |
158 | || PyBool_Check(value) |
159 | || PyUnicode_CheckExact(value) |
160 | || PyBytes_CheckExact844 (value)) |
161 | return 1; |
162 | |
163 | if (PyTuple_CheckExact(value) || PyFrozenSet_CheckExact14 (value)) { |
164 | if (++state->recursion_depth > state->recursion_limit) { Branch (164:13): [True: 0, False: 16]
|
165 | PyErr_SetString(PyExc_RecursionError, |
166 | "maximum recursion depth exceeded during compilation"); |
167 | return 0; |
168 | } |
169 | |
170 | PyObject *it = PyObject_GetIter(value); |
171 | if (it == NULL) Branch (171:13): [True: 0, False: 16]
|
172 | return 0; |
173 | |
174 | while (16 1) { Branch (174:16): [Folded - Ignored]
|
175 | PyObject *item = PyIter_Next(it); |
176 | if (item == NULL) { Branch (176:17): [True: 14, False: 42]
|
177 | if (PyErr_Occurred()) { Branch (177:21): [True: 0, False: 14]
|
178 | Py_DECREF(it); |
179 | return 0; |
180 | } |
181 | break; |
182 | } |
183 | |
184 | if (!validate_constant(state, item)) { Branch (184:17): [True: 2, False: 40]
|
185 | Py_DECREF(it); |
186 | Py_DECREF(item); |
187 | return 0; |
188 | } |
189 | Py_DECREF(item); |
190 | } |
191 | |
192 | Py_DECREF(it); |
193 | --state->recursion_depth; |
194 | return 1; |
195 | } |
196 | |
197 | if (!PyErr_Occurred()) { Branch (197:9): [True: 7, False: 0]
|
198 | PyErr_Format(PyExc_TypeError, |
199 | "got an invalid type in Constant: %s", |
200 | _PyType_Name(Py_TYPE(value))); |
201 | } |
202 | return 0; |
203 | } |
204 | |
205 | static int |
206 | validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx) |
207 | { |
208 | VALIDATE_POSITIONS267k (exp); |
209 | int ret = -1; |
210 | if (++state->recursion_depth > state->recursion_limit) { Branch (210:9): [True: 0, False: 267k]
|
211 | PyErr_SetString(PyExc_RecursionError, |
212 | "maximum recursion depth exceeded during compilation"); |
213 | return 0; |
214 | } |
215 | int check_ctx = 1; |
216 | expr_context_ty actual_ctx; |
217 | |
218 | /* First check expression context. */ |
219 | switch (exp->kind) { |
220 | case Attribute_kind: Branch (220:5): [True: 35.1k, False: 232k]
|
221 | actual_ctx = exp->v.Attribute.ctx; |
222 | break; |
223 | case Subscript_kind: Branch (223:5): [True: 4.94k, False: 262k]
|
224 | actual_ctx = exp->v.Subscript.ctx; |
225 | break; |
226 | case Starred_kind: Branch (226:5): [True: 315, False: 267k]
|
227 | actual_ctx = exp->v.Starred.ctx; |
228 | break; |
229 | case Name_kind: Branch (229:5): [True: 119k, False: 148k]
|
230 | if (!validate_name(exp->v.Name.id)) { Branch (230:13): [True: 3, False: 119k]
|
231 | return 0; |
232 | } |
233 | actual_ctx = exp->v.Name.ctx; |
234 | break; |
235 | case List_kind: Branch (235:5): [True: 1.48k, False: 265k]
|
236 | actual_ctx = exp->v.List.ctx; |
237 | break; |
238 | case Tuple_kind: Branch (238:5): [True: 5.24k, False: 262k]
|
239 | actual_ctx = exp->v.Tuple.ctx; |
240 | break; |
241 | default: Branch (241:5): [True: 100k, False: 166k]
|
242 | if (ctx != Load) { Branch (242:13): [True: 1, False: 100k]
|
243 | PyErr_Format(PyExc_ValueError, "expression which can't be " |
244 | "assigned to in %s context", expr_context_name(ctx)); |
245 | return 0; |
246 | } |
247 | check_ctx = 0; |
248 | /* set actual_ctx to prevent gcc warning */ |
249 | actual_ctx = 0; |
250 | } |
251 | if (check_ctx && actual_ctx != ctx166k ) { Branch (251:9): [True: 166k, False: 100k]
Branch (251:22): [True: 86, False: 166k]
|
252 | PyErr_Format(PyExc_ValueError, "expression must have %s context but has %s instead", |
253 | expr_context_name(ctx), expr_context_name(actual_ctx)); |
254 | return 0; |
255 | } |
256 | |
257 | /* Now validate expression. */ |
258 | switch (exp->kind) { Branch (258:13): [True: 0, False: 267k]
|
259 | case BoolOp_kind: Branch (259:5): [True: 2.06k, False: 265k]
|
260 | if (asdl_seq_LEN(exp->v.BoolOp.values) < 2) { Branch (260:13): [True: 2, False: 2.06k]
|
261 | PyErr_SetString(PyExc_ValueError, "BoolOp with less than 2 values"); |
262 | return 0; |
263 | } |
264 | ret = validate_exprs(state, exp->v.BoolOp.values, Load, 0); |
265 | break; |
266 | case BinOp_kind: Branch (266:5): [True: 6.63k, False: 260k]
|
267 | ret = validate_expr(state, exp->v.BinOp.left, Load) && Branch (267:15): [True: 6.63k, False: 0]
|
268 | validate_expr(state, exp->v.BinOp.right, Load); Branch (268:13): [True: 6.63k, False: 0]
|
269 | break; |
270 | case UnaryOp_kind: Branch (270:5): [True: 3.00k, False: 264k]
|
271 | ret = validate_expr(state, exp->v.UnaryOp.operand, Load); |
272 | break; |
273 | case Lambda_kind: Branch (273:5): [True: 168, False: 267k]
|
274 | ret = validate_arguments(state, exp->v.Lambda.args) && Branch (274:15): [True: 161, False: 7]
|
275 | validate_expr(state, exp->v.Lambda.body, Load)161 ; Branch (275:13): [True: 160, False: 1]
|
276 | break; |
277 | case IfExp_kind: Branch (277:5): [True: 238, False: 266k]
|
278 | ret = validate_expr(state, exp->v.IfExp.test, Load) && Branch (278:15): [True: 237, False: 1]
|
279 | validate_expr(state, exp->v.IfExp.body, Load)237 && Branch (279:13): [True: 236, False: 1]
|
280 | validate_expr(state, exp->v.IfExp.orelse, Load)236 ; Branch (280:13): [True: 235, False: 1]
|
281 | break; |
282 | case Dict_kind: Branch (282:5): [True: 625, False: 266k]
|
283 | if (asdl_seq_LEN(exp->v.Dict.keys) != asdl_seq_LEN(exp->v.Dict.values)) { Branch (283:13): [True: 1, False: 624]
|
284 | PyErr_SetString(PyExc_ValueError, |
285 | "Dict doesn't have the same number of keys as values"); |
286 | return 0; |
287 | } |
288 | /* null_ok=1 for keys expressions to allow dict unpacking to work in |
289 | dict literals, i.e. ``{**{a:b}}`` */ |
290 | ret = validate_exprs(state, exp->v.Dict.keys, Load, /*null_ok=*/ 1) && Branch (290:15): [True: 624, False: 0]
|
291 | validate_exprs(state, exp->v.Dict.values, Load, /*null_ok=*/ 0); Branch (291:13): [True: 623, False: 1]
|
292 | break; |
293 | case Set_kind: Branch (293:5): [True: 114, False: 267k]
|
294 | ret = validate_exprs(state, exp->v.Set.elts, Load, 0); |
295 | break; |
296 | #define COMP(NAME) \ |
297 | case NAME ## _kind: \ |
298 | ret = validate_comprehension(state, exp->v.NAME.generators) && \ |
299 | validate_expr(state, exp->v.NAME.elt, Load)560 ; \ |
300 | break; |
301 | COMP320 (ListComp) |
302 | COMP23 (SetComp) |
303 | COMP232 (GeneratorExp) |
304 | #undef COMP |
305 | case DictComp_kind: Branch (305:5): [True: 37, False: 267k]
|
306 | ret = validate_comprehension(state, exp->v.DictComp.generators) && Branch (306:15): [True: 32, False: 5]
|
307 | validate_expr(state, exp->v.DictComp.key, Load)32 && Branch (307:13): [True: 31, False: 1]
|
308 | validate_expr(state, exp->v.DictComp.value, Load)31 ; Branch (308:13): [True: 30, False: 1]
|
309 | break; |
310 | case Yield_kind: Branch (310:5): [True: 210, False: 267k]
|
311 | ret = !exp->v.Yield.value || validate_expr(state, exp->v.Yield.value, Load)203 ; Branch (311:15): [True: 7, False: 203]
Branch (311:38): [True: 202, False: 1]
|
312 | break; |
313 | case YieldFrom_kind: Branch (313:5): [True: 51, False: 267k]
|
314 | ret = validate_expr(state, exp->v.YieldFrom.value, Load); |
315 | break; |
316 | case Await_kind: Branch (316:5): [True: 14, False: 267k]
|
317 | ret = validate_expr(state, exp->v.Await.value, Load); |
318 | break; |
319 | case Compare_kind: Branch (319:5): [True: 8.17k, False: 259k]
|
320 | if (!asdl_seq_LEN(exp->v.Compare.comparators)) { Branch (320:13): [True: 1, False: 8.17k]
|
321 | PyErr_SetString(PyExc_ValueError, "Compare with no comparators"); |
322 | return 0; |
323 | } |
324 | if (asdl_seq_LEN(exp->v.Compare.comparators) != Branch (324:13): [True: 1, False: 8.17k]
|
325 | asdl_seq_LEN(exp->v.Compare.ops)) { |
326 | PyErr_SetString(PyExc_ValueError, "Compare has a different number " |
327 | "of comparators and operands"); |
328 | return 0; |
329 | } |
330 | ret = validate_exprs(state, exp->v.Compare.comparators, Load, 0) && Branch (330:15): [True: 8.17k, False: 0]
|
331 | validate_expr(state, exp->v.Compare.left, Load); Branch (331:13): [True: 8.17k, False: 0]
|
332 | break; |
333 | case Call_kind: Branch (333:5): [True: 30.1k, False: 237k]
|
334 | ret = validate_expr(state, exp->v.Call.func, Load) && Branch (334:15): [True: 30.1k, False: 1]
|
335 | validate_exprs(state, exp->v.Call.args, Load, 0)30.1k && Branch (335:13): [True: 30.1k, False: 1]
|
336 | validate_keywords(state, exp->v.Call.keywords)30.1k ; Branch (336:13): [True: 30.1k, False: 1]
|
337 | break; |
338 | case Constant_kind: Branch (338:5): [True: 46.6k, False: 220k]
|
339 | if (!validate_constant(state, exp->v.Constant.value)) { Branch (339:13): [True: 7, False: 46.6k]
|
340 | return 0; |
341 | } |
342 | ret = 1; |
343 | break; |
344 | case JoinedStr_kind: Branch (344:5): [True: 391, False: 266k]
|
345 | ret = validate_exprs(state, exp->v.JoinedStr.values, Load, 0); |
346 | break; |
347 | case FormattedValue_kind: Branch (347:5): [True: 555, False: 266k]
|
348 | if (validate_expr(state, exp->v.FormattedValue.value, Load) == 0) Branch (348:13): [True: 0, False: 555]
|
349 | return 0; |
350 | if (exp->v.FormattedValue.format_spec) { Branch (350:13): [True: 19, False: 536]
|
351 | ret = validate_expr(state, exp->v.FormattedValue.format_spec, Load); |
352 | break; |
353 | } |
354 | ret = 1; |
355 | break; |
356 | case Attribute_kind: Branch (356:5): [True: 35.1k, False: 232k]
|
357 | ret = validate_expr(state, exp->v.Attribute.value, Load); |
358 | break; |
359 | case Subscript_kind: Branch (359:5): [True: 4.94k, False: 262k]
|
360 | ret = validate_expr(state, exp->v.Subscript.slice, Load) && Branch (360:15): [True: 4.94k, False: 5]
|
361 | validate_expr(state, exp->v.Subscript.value, Load)4.94k ; Branch (361:13): [True: 4.94k, False: 1]
|
362 | break; |
363 | case Starred_kind: Branch (363:5): [True: 315, False: 266k]
|
364 | ret = validate_expr(state, exp->v.Starred.value, ctx); |
365 | break; |
366 | case Slice_kind: Branch (366:5): [True: 1.29k, False: 265k]
|
367 | ret = (!exp->v.Slice.lower || validate_expr(state, exp->v.Slice.lower, Load)774 ) && Branch (367:16): [True: 520, False: 774]
Branch (367:39): [True: 773, False: 1]
|
368 | (1.29k !exp->v.Slice.upper1.29k || validate_expr(state, exp->v.Slice.upper, Load)796 ) && Branch (368:14): [True: 497, False: 796]
Branch (368:37): [True: 795, False: 1]
|
369 | (1.29k !exp->v.Slice.step1.29k || validate_expr(state, exp->v.Slice.step, Load)31 ); Branch (369:14): [True: 1.26k, False: 31]
Branch (369:36): [True: 30, False: 1]
|
370 | break; |
371 | case List_kind: Branch (371:5): [True: 1.48k, False: 265k]
|
372 | ret = validate_exprs(state, exp->v.List.elts, ctx, 0); |
373 | break; |
374 | case Tuple_kind: Branch (374:5): [True: 5.24k, False: 261k]
|
375 | ret = validate_exprs(state, exp->v.Tuple.elts, ctx, 0); |
376 | break; |
377 | case NamedExpr_kind: Branch (377:5): [True: 22, False: 267k]
|
378 | ret = validate_expr(state, exp->v.NamedExpr.value, Load); |
379 | break; |
380 | /* This last case doesn't have any checking. */ |
381 | case Name_kind: Branch (381:5): [True: 119k, False: 148k]
|
382 | ret = 1; |
383 | break; |
384 | // No default case so compiler emits warning for unhandled cases |
385 | } |
386 | if (ret < 0) { Branch (386:9): [True: 0, False: 267k]
|
387 | PyErr_SetString(PyExc_SystemError, "unexpected expression"); |
388 | ret = 0; |
389 | } |
390 | state->recursion_depth--; |
391 | return ret; |
392 | } |
393 | |
394 | |
395 | // Note: the ensure_literal_* functions are only used to validate a restricted |
396 | // set of non-recursive literals that have already been checked with |
397 | // validate_expr, so they don't accept the validator state |
398 | static int |
399 | ensure_literal_number(expr_ty exp, bool allow_real, bool allow_imaginary) |
400 | { |
401 | assert(exp->kind == Constant_kind); |
402 | PyObject *value = exp->v.Constant.value; |
403 | return (allow_real && PyFloat_CheckExact(value)) || Branch (403:13): [True: 0, False: 0]
|
404 | (allow_real && PyLong_CheckExact(value)) || Branch (404:13): [True: 0, False: 0]
|
405 | (allow_imaginary && PyComplex_CheckExact(value)); Branch (405:13): [True: 0, False: 0]
|
406 | } |
407 | |
408 | static int |
409 | ensure_literal_negative(expr_ty exp, bool allow_real, bool allow_imaginary) |
410 | { |
411 | assert(exp->kind == UnaryOp_kind); |
412 | // Must be negation ... |
413 | if (exp->v.UnaryOp.op != USub) { Branch (413:9): [True: 0, False: 0]
|
414 | return 0; |
415 | } |
416 | // ... of a constant ... |
417 | expr_ty operand = exp->v.UnaryOp.operand; |
418 | if (operand->kind != Constant_kind) { Branch (418:9): [True: 0, False: 0]
|
419 | return 0; |
420 | } |
421 | // ... number |
422 | return ensure_literal_number(operand, allow_real, allow_imaginary); |
423 | } |
424 | |
425 | static int |
426 | ensure_literal_complex(expr_ty exp) |
427 | { |
428 | assert(exp->kind == BinOp_kind); |
429 | expr_ty left = exp->v.BinOp.left; |
430 | expr_ty right = exp->v.BinOp.right; |
431 | // Ensure op is addition or subtraction |
432 | if (exp->v.BinOp.op != Add && exp->v.BinOp.op != Sub) { Branch (432:9): [True: 0, False: 0]
Branch (432:35): [True: 0, False: 0]
|
433 | return 0; |
434 | } |
435 | // Check LHS is a real number (potentially signed) |
436 | switch (left->kind) |
437 | { |
438 | case Constant_kind: Branch (438:9): [True: 0, False: 0]
|
439 | if (!ensure_literal_number(left, /*real=*/true, /*imaginary=*/false)) { Branch (439:17): [True: 0, False: 0]
|
440 | return 0; |
441 | } |
442 | break; |
443 | case UnaryOp_kind: Branch (443:9): [True: 0, False: 0]
|
444 | if (!ensure_literal_negative(left, /*real=*/true, /*imaginary=*/false)) { Branch (444:17): [True: 0, False: 0]
|
445 | return 0; |
446 | } |
447 | break; |
448 | default: Branch (448:9): [True: 0, False: 0]
|
449 | return 0; |
450 | } |
451 | // Check RHS is an imaginary number (no separate sign allowed) |
452 | switch (right->kind) |
453 | { |
454 | case Constant_kind: Branch (454:9): [True: 0, False: 0]
|
455 | if (!ensure_literal_number(right, /*real=*/false, /*imaginary=*/true)) { Branch (455:17): [True: 0, False: 0]
|
456 | return 0; |
457 | } |
458 | break; |
459 | default: Branch (459:9): [True: 0, False: 0]
|
460 | return 0; |
461 | } |
462 | return 1; |
463 | } |
464 | |
465 | static int |
466 | validate_pattern_match_value(struct validator *state, expr_ty exp) |
467 | { |
468 | if (!validate_expr(state, exp, Load)) { Branch (468:9): [True: 2, False: 9]
|
469 | return 0; |
470 | } |
471 | |
472 | switch (exp->kind) |
473 | { |
474 | case Constant_kind: Branch (474:9): [True: 8, False: 1]
|
475 | /* Ellipsis and immutable sequences are not allowed. |
476 | For True, False and None, MatchSingleton() should |
477 | be used */ |
478 | if (!validate_expr(state, exp, Load)) { Branch (478:17): [True: 0, False: 8]
|
479 | return 0; |
480 | } |
481 | PyObject *literal = exp->v.Constant.value; |
482 | if (PyLong_CheckExact(literal) || PyFloat_CheckExact(literal) || |
483 | PyBytes_CheckExact(literal) || PyComplex_CheckExact(literal) || |
484 | PyUnicode_CheckExact5 (literal)) { |
485 | return 1; |
486 | } |
487 | PyErr_SetString(PyExc_ValueError, |
488 | "unexpected constant inside of a literal pattern"); |
489 | return 0; |
490 | case Attribute_kind: Branch (490:9): [True: 0, False: 9]
|
491 | // Constants and attribute lookups are always permitted |
492 | return 1; |
493 | case UnaryOp_kind: Branch (493:9): [True: 0, False: 9]
|
494 | // Negated numbers are permitted (whether real or imaginary) |
495 | // Compiler will complain if AST folding doesn't create a constant |
496 | if (ensure_literal_negative(exp, /*real=*/true, /*imaginary=*/true)) { Branch (496:17): [True: 0, False: 0]
|
497 | return 1; |
498 | } |
499 | break; |
500 | case BinOp_kind: Branch (500:9): [True: 0, False: 9]
|
501 | // Complex literals are permitted |
502 | // Compiler will complain if AST folding doesn't create a constant |
503 | if (ensure_literal_complex(exp)) { Branch (503:17): [True: 0, False: 0]
|
504 | return 1; |
505 | } |
506 | break; |
507 | case JoinedStr_kind: Branch (507:9): [True: 0, False: 9]
|
508 | // Handled in the later stages |
509 | return 1; |
510 | default: Branch (510:9): [True: 1, False: 8]
|
511 | break; |
512 | } |
513 | PyErr_SetString(PyExc_ValueError, |
514 | "patterns may only match literals and attribute lookups"); |
515 | return 0; |
516 | } |
517 | |
518 | static int |
519 | validate_capture(PyObject *name) |
520 | { |
521 | if (_PyUnicode_EqualToASCIIString(name, "_")) { Branch (521:9): [True: 3, False: 7]
|
522 | PyErr_Format(PyExc_ValueError, "can't capture name '_' in patterns"); |
523 | return 0; |
524 | } |
525 | return validate_name(name); |
526 | } |
527 | |
528 | static int |
529 | validate_pattern(struct validator *state, pattern_ty p, int star_ok) |
530 | { |
531 | VALIDATE_POSITIONS48 (p); |
532 | int ret = -1; |
533 | if (++state->recursion_depth > state->recursion_limit) { Branch (533:9): [True: 0, False: 48]
|
534 | PyErr_SetString(PyExc_RecursionError, |
535 | "maximum recursion depth exceeded during compilation"); |
536 | return 0; |
537 | } |
538 | switch (p->kind) { Branch (538:13): [True: 0, False: 48]
|
539 | case MatchValue_kind: Branch (539:9): [True: 10, False: 38]
|
540 | ret = validate_pattern_match_value(state, p->v.MatchValue.value); |
541 | break; |
542 | case MatchSingleton_kind: Branch (542:9): [True: 6, False: 42]
|
543 | ret = p->v.MatchSingleton.value == Py_None || PyBool_Check(p->v.MatchSingleton.value); Branch (543:19): [True: 1, False: 5]
|
544 | if (!ret) { Branch (544:17): [True: 5, False: 1]
|
545 | PyErr_SetString(PyExc_ValueError, |
546 | "MatchSingleton can only contain True, False and None"); |
547 | } |
548 | break; |
549 | case MatchSequence_kind: Branch (549:9): [True: 5, False: 43]
|
550 | ret = validate_patterns(state, p->v.MatchSequence.patterns, /*star_ok=*/1); |
551 | break; |
552 | case MatchMapping_kind: Branch (552:9): [True: 4, False: 44]
|
553 | if (asdl_seq_LEN(p->v.MatchMapping.keys) != asdl_seq_LEN(p->v.MatchMapping.patterns)) { Branch (553:17): [True: 1, False: 3]
|
554 | PyErr_SetString(PyExc_ValueError, |
555 | "MatchMapping doesn't have the same number of keys as patterns"); |
556 | ret = 0; |
557 | break; |
558 | } |
559 | |
560 | if (p->v.MatchMapping.rest && !validate_capture(p->v.MatchMapping.rest)) { Branch (560:17): [True: 3, False: 0]
Branch (560:43): [True: 2, False: 1]
|
561 | ret = 0; |
562 | break; |
563 | } |
564 | |
565 | asdl_expr_seq *keys = p->v.MatchMapping.keys; |
566 | for (Py_ssize_t i = 0; i < asdl_seq_LEN(keys); i++1 ) { Branch (566:36): [True: 2, False: 0]
|
567 | expr_ty key = asdl_seq_GET(keys, i); |
568 | if (key->kind == Constant_kind) { Branch (568:21): [True: 1, False: 1]
|
569 | PyObject *literal = key->v.Constant.value; |
570 | if (literal == Py_None || PyBool_Check(literal)) { Branch (570:25): [True: 0, False: 1]
|
571 | /* validate_pattern_match_value will ensure the key |
572 | doesn't contain True, False and None but it is |
573 | syntactically valid, so we will pass those on in |
574 | a special case. */ |
575 | continue; |
576 | } |
577 | } |
578 | if (!validate_pattern_match_value(state, key)) { Branch (578:21): [True: 1, False: 0]
|
579 | ret = 0; |
580 | break; |
581 | } |
582 | } |
583 | |
584 | ret = validate_patterns(state, p->v.MatchMapping.patterns, /*star_ok=*/0); |
585 | break; |
586 | case MatchClass_kind: Branch (586:9): [True: 10, False: 38]
|
587 | if (asdl_seq_LEN(p->v.MatchClass.kwd_attrs) != asdl_seq_LEN(p->v.MatchClass.kwd_patterns)) { Branch (587:17): [True: 2, False: 8]
|
588 | PyErr_SetString(PyExc_ValueError, |
589 | "MatchClass doesn't have the same number of keyword attributes as patterns"); |
590 | ret = 0; |
591 | break; |
592 | } |
593 | if (!validate_expr(state, p->v.MatchClass.cls, Load)) { Branch (593:17): [True: 0, False: 8]
|
594 | ret = 0; |
595 | break; |
596 | } |
597 | |
598 | expr_ty cls = p->v.MatchClass.cls; |
599 | while (1) { Branch (599:20): [Folded - Ignored]
|
600 | if (cls->kind == Name_kind) { Branch (600:21): [True: 7, False: 6]
|
601 | break; |
602 | } |
603 | else if (cls->kind == Attribute_kind) { Branch (603:26): [True: 5, False: 1]
|
604 | cls = cls->v.Attribute.value; |
605 | continue; |
606 | } |
607 | else { |
608 | PyErr_SetString(PyExc_ValueError, |
609 | "MatchClass cls field can only contain Name or Attribute nodes."); |
610 | ret = 0; |
611 | break; |
612 | } |
613 | } |
614 | |
615 | for (Py_ssize_t i = 0; i < asdl_seq_LEN(p->v.MatchClass.kwd_attrs); i++0 ) { Branch (615:36): [True: 1, False: 7]
|
616 | PyObject *identifier = asdl_seq_GET(p->v.MatchClass.kwd_attrs, i); |
617 | if (!validate_name(identifier)) { Branch (617:21): [True: 1, False: 0]
|
618 | ret = 0; |
619 | break; |
620 | } |
621 | } |
622 | |
623 | if (!validate_patterns(state, p->v.MatchClass.patterns, /*star_ok=*/0)) { Branch (623:17): [True: 2, False: 6]
|
624 | ret = 0; |
625 | break; |
626 | } |
627 | |
628 | ret = validate_patterns(state, p->v.MatchClass.kwd_patterns, /*star_ok=*/0); |
629 | break; |
630 | case MatchStar_kind: Branch (630:9): [True: 4, False: 44]
|
631 | if (!star_ok) { Branch (631:17): [True: 2, False: 2]
|
632 | PyErr_SetString(PyExc_ValueError, "can't use MatchStar here"); |
633 | ret = 0; |
634 | break; |
635 | } |
636 | ret = p->v.MatchStar.name == NULL || validate_capture(p->v.MatchStar.name); Branch (636:19): [True: 0, False: 2]
Branch (636:50): [True: 0, False: 2]
|
637 | break; |
638 | case MatchAs_kind: Branch (638:9): [True: 6, False: 42]
|
639 | if (p->v.MatchAs.name && !validate_capture(p->v.MatchAs.name)5 ) { Branch (639:17): [True: 5, False: 1]
Branch (639:38): [True: 2, False: 3]
|
640 | ret = 0; |
641 | break; |
642 | } |
643 | if (p->v.MatchAs.pattern == NULL) { Branch (643:17): [True: 4, False: 0]
|
644 | ret = 1; |
645 | } |
646 | else if (p->v.MatchAs.name == NULL) { Branch (646:22): [True: 0, False: 0]
|
647 | PyErr_SetString(PyExc_ValueError, |
648 | "MatchAs must specify a target name if a pattern is given"); |
649 | ret = 0; |
650 | } |
651 | else { |
652 | ret = validate_pattern(state, p->v.MatchAs.pattern, /*star_ok=*/0); |
653 | } |
654 | break; |
655 | case MatchOr_kind: Branch (655:9): [True: 3, False: 45]
|
656 | if (asdl_seq_LEN(p->v.MatchOr.patterns) < 2) { Branch (656:17): [True: 2, False: 1]
|
657 | PyErr_SetString(PyExc_ValueError, |
658 | "MatchOr requires at least 2 patterns"); |
659 | ret = 0; |
660 | break; |
661 | } |
662 | ret = validate_patterns(state, p->v.MatchOr.patterns, /*star_ok=*/0); |
663 | break; |
664 | // No default case, so the compiler will emit a warning if new pattern |
665 | // kinds are added without being handled here |
666 | } |
667 | if (ret < 0) { Branch (667:9): [True: 0, False: 48]
|
668 | PyErr_SetString(PyExc_SystemError, "unexpected pattern"); |
669 | ret = 0; |
670 | } |
671 | state->recursion_depth--; |
672 | return ret; |
673 | } |
674 | |
675 | static int |
676 | _validate_nonempty_seq(asdl_seq *seq, const char *what, const char *owner) |
677 | { |
678 | if (asdl_seq_LEN(seq)) |
679 | return 1; |
680 | PyErr_Format(PyExc_ValueError, "empty %s on %s", what, owner); |
681 | return 0; |
682 | } |
683 | #define validate_nonempty_seq(seq, what, owner) _validate_nonempty_seq((asdl_seq*)seq, what, owner42.1k ) |
684 | |
685 | static int |
686 | validate_assignlist(struct validator *state, asdl_expr_seq *targets, expr_context_ty ctx) |
687 | { |
688 | return validate_nonempty_seq(targets, "targets", ctx == Del ? "Delete" : "Assign") && |
689 | validate_exprs(state, targets, ctx, 0)21.0k ; Branch (689:9): [True: 21.0k, False: 6]
|
690 | } |
691 | |
692 | static int |
693 | validate_body(struct validator *state, asdl_stmt_seq *body, const char *owner) |
694 | { |
695 | return validate_nonempty_seq(body, "body", owner) && validate_stmts(state, body)24.5k ; Branch (695:58): [True: 24.5k, False: 5]
|
696 | } |
697 | |
698 | static int |
699 | validate_stmt(struct validator *state, stmt_ty stmt) |
700 | { |
701 | VALIDATE_POSITIONS69.9k (stmt); |
702 | int ret = -1; |
703 | Py_ssize_t i; |
704 | if (++state->recursion_depth > state->recursion_limit) { Branch (704:9): [True: 0, False: 69.9k]
|
705 | PyErr_SetString(PyExc_RecursionError, |
706 | "maximum recursion depth exceeded during compilation"); |
707 | return 0; |
708 | } |
709 | switch (stmt->kind) { Branch (709:13): [True: 0, False: 69.9k]
|
710 | case FunctionDef_kind: Branch (710:5): [True: 7.39k, False: 62.5k]
|
711 | ret = validate_body(state, stmt->v.FunctionDef.body, "FunctionDef") && Branch (711:15): [True: 7.39k, False: 1]
|
712 | validate_arguments(state, stmt->v.FunctionDef.args)7.39k && Branch (712:13): [True: 7.38k, False: 7]
|
713 | validate_exprs(state, stmt->v.FunctionDef.decorator_list, Load, 0)7.38k && Branch (713:13): [True: 7.38k, False: 1]
|
714 | (7.38k !stmt->v.FunctionDef.returns7.38k || Branch (714:14): [True: 7.33k, False: 56]
|
715 | validate_expr(state, stmt->v.FunctionDef.returns, Load)56 ); Branch (715:14): [True: 55, False: 1]
|
716 | break; |
717 | case ClassDef_kind: Branch (717:5): [True: 830, False: 69.1k]
|
718 | ret = validate_body(state, stmt->v.ClassDef.body, "ClassDef") && Branch (718:15): [True: 828, False: 2]
|
719 | validate_exprs(state, stmt->v.ClassDef.bases, Load, 0)828 && Branch (719:13): [True: 827, False: 1]
|
720 | validate_keywords(state, stmt->v.ClassDef.keywords)827 && Branch (720:13): [True: 826, False: 1]
|
721 | validate_exprs(state, stmt->v.ClassDef.decorator_list, Load, 0)826 ; Branch (721:13): [True: 825, False: 1]
|
722 | break; |
723 | case Return_kind: Branch (723:5): [True: 7.06k, False: 62.8k]
|
724 | ret = !stmt->v.Return.value || validate_expr(state, stmt->v.Return.value, Load)6.72k ; Branch (724:15): [True: 340, False: 6.72k]
Branch (724:40): [True: 6.72k, False: 0]
|
725 | break; |
726 | case Delete_kind: Branch (726:5): [True: 223, False: 69.7k]
|
727 | ret = validate_assignlist(state, stmt->v.Delete.targets, Del); |
728 | break; |
729 | case Assign_kind: Branch (729:5): [True: 20.8k, False: 49.1k]
|
730 | ret = validate_assignlist(state, stmt->v.Assign.targets, Store) && Branch (730:15): [True: 20.8k, False: 5]
|
731 | validate_expr(state, stmt->v.Assign.value, Load)20.8k ; Branch (731:13): [True: 20.8k, False: 2]
|
732 | break; |
733 | case AugAssign_kind: Branch (733:5): [True: 856, False: 69.0k]
|
734 | ret = validate_expr(state, stmt->v.AugAssign.target, Store) && Branch (734:15): [True: 855, False: 1]
|
735 | validate_expr(state, stmt->v.AugAssign.value, Load)855 ; Branch (735:13): [True: 854, False: 1]
|
736 | break; |
737 | case AnnAssign_kind: Branch (737:5): [True: 37, False: 69.9k]
|
738 | if (stmt->v.AnnAssign.target->kind != Name_kind && Branch (738:13): [True: 9, False: 28]
|
739 | stmt->v.AnnAssign.simple9 ) { Branch (739:13): [True: 0, False: 9]
|
740 | PyErr_SetString(PyExc_TypeError, |
741 | "AnnAssign with simple non-Name target"); |
742 | return 0; |
743 | } |
744 | ret = validate_expr(state, stmt->v.AnnAssign.target, Store) && Branch (744:15): [True: 37, False: 0]
|
745 | (!stmt->v.AnnAssign.value || Branch (745:17): [True: 26, False: 11]
|
746 | validate_expr(state, stmt->v.AnnAssign.value, Load)11 ) && Branch (746:17): [True: 11, False: 0]
|
747 | validate_expr(state, stmt->v.AnnAssign.annotation, Load); Branch (747:16): [True: 37, False: 0]
|
748 | break; |
749 | case For_kind: Branch (749:5): [True: 1.39k, False: 68.5k]
|
750 | ret = validate_expr(state, stmt->v.For.target, Store) && Branch (750:15): [True: 1.39k, False: 1]
|
751 | validate_expr(state, stmt->v.For.iter, Load)1.39k && Branch (751:13): [True: 1.39k, False: 1]
|
752 | validate_body(state, stmt->v.For.body, "For")1.39k && Branch (752:13): [True: 1.39k, False: 2]
|
753 | validate_stmts(state, stmt->v.For.orelse)1.39k ; Branch (753:13): [True: 1.39k, False: 1]
|
754 | break; |
755 | case AsyncFor_kind: Branch (755:5): [True: 6, False: 69.9k]
|
756 | ret = validate_expr(state, stmt->v.AsyncFor.target, Store) && Branch (756:15): [True: 6, False: 0]
|
757 | validate_expr(state, stmt->v.AsyncFor.iter, Load) && Branch (757:13): [True: 6, False: 0]
|
758 | validate_body(state, stmt->v.AsyncFor.body, "AsyncFor") && Branch (758:13): [True: 6, False: 0]
|
759 | validate_stmts(state, stmt->v.AsyncFor.orelse); Branch (759:13): [True: 6, False: 0]
|
760 | break; |
761 | case While_kind: Branch (761:5): [True: 443, False: 69.4k]
|
762 | ret = validate_expr(state, stmt->v.While.test, Load) && Branch (762:15): [True: 442, False: 1]
|
763 | validate_body(state, stmt->v.While.body, "While")442 && Branch (763:13): [True: 441, False: 1]
|
764 | validate_stmts(state, stmt->v.While.orelse)441 ; Branch (764:13): [True: 440, False: 1]
|
765 | break; |
766 | case If_kind: Branch (766:5): [True: 11.1k, False: 58.7k]
|
767 | ret = validate_expr(state, stmt->v.If.test, Load) && Branch (767:15): [True: 11.1k, False: 1]
|
768 | validate_body(state, stmt->v.If.body, "If")11.1k && Branch (768:13): [True: 11.1k, False: 2]
|
769 | validate_stmts(state, stmt->v.If.orelse)11.1k ; Branch (769:13): [True: 11.1k, False: 1]
|
770 | break; |
771 | case With_kind: Branch (771:5): [True: 385, False: 69.5k]
|
772 | if (!validate_nonempty_seq(stmt->v.With.items, "items", "With")) Branch (772:13): [True: 1, False: 384]
|
773 | return 0; |
774 | for (i = 0; 384 i < asdl_seq_LEN(stmt->v.With.items); i++404 ) { Branch (774:21): [True: 406, False: 382]
|
775 | withitem_ty item = asdl_seq_GET(stmt->v.With.items, i); |
776 | if (!validate_expr(state, item->context_expr, Load) || Branch (776:17): [True: 1, False: 405]
|
777 | (405 item->optional_vars405 && !validate_expr(state, item->optional_vars, Store)186 )) Branch (777:18): [True: 186, False: 219]
Branch (777:41): [True: 1, False: 185]
|
778 | return 0; |
779 | } |
780 | ret = validate_body(state, stmt->v.With.body, "With"); |
781 | break; |
782 | case AsyncWith_kind: Branch (782:5): [True: 9, False: 69.9k]
|
783 | if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith")) Branch (783:13): [True: 0, False: 9]
|
784 | return 0; |
785 | for (i = 0; 9 i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++12 ) { Branch (785:21): [True: 12, False: 9]
|
786 | withitem_ty item = asdl_seq_GET(stmt->v.AsyncWith.items, i); |
787 | if (!validate_expr(state, item->context_expr, Load) || Branch (787:17): [True: 0, False: 12]
|
788 | (item->optional_vars && !validate_expr(state, item->optional_vars, Store)7 )) Branch (788:18): [True: 7, False: 5]
Branch (788:41): [True: 0, False: 7]
|
789 | return 0; |
790 | } |
791 | ret = validate_body(state, stmt->v.AsyncWith.body, "AsyncWith"); |
792 | break; |
793 | case Match_kind: Branch (793:5): [True: 29, False: 69.9k]
|
794 | if (!validate_expr(state, stmt->v.Match.subject, Load) Branch (794:13): [True: 0, False: 29]
|
795 | || !validate_nonempty_seq(stmt->v.Match.cases, "cases", "Match")) { Branch (795:16): [True: 0, False: 29]
|
796 | return 0; |
797 | } |
798 | for (i = 0; 29 i < asdl_seq_LEN(stmt->v.Match.cases); i++10 ) { Branch (798:21): [True: 33, False: 6]
|
799 | match_case_ty m = asdl_seq_GET(stmt->v.Match.cases, i); |
800 | if (!validate_pattern(state, m->pattern, /*star_ok=*/0) Branch (800:17): [True: 23, False: 10]
|
801 | || (10 m->guard10 && !validate_expr(state, m->guard, Load)1 ) Branch (801:21): [True: 1, False: 9]
Branch (801:33): [True: 0, False: 1]
|
802 | || !validate_body(state, m->body, "match_case")10 ) { Branch (802:20): [True: 0, False: 10]
|
803 | return 0; |
804 | } |
805 | } |
806 | ret = 1; |
807 | break; |
808 | case Raise_kind: Branch (808:5): [True: 2.31k, False: 67.6k]
|
809 | if (stmt->v.Raise.exc) { Branch (809:13): [True: 2.14k, False: 164]
|
810 | ret = validate_expr(state, stmt->v.Raise.exc, Load) && Branch (810:19): [True: 2.14k, False: 1]
|
811 | (2.14k !stmt->v.Raise.cause2.14k || validate_expr(state, stmt->v.Raise.cause, Load)132 ); Branch (811:18): [True: 2.01k, False: 132]
Branch (811:42): [True: 131, False: 1]
|
812 | break; |
813 | } |
814 | if (stmt->v.Raise.cause) { Branch (814:13): [True: 1, False: 163]
|
815 | PyErr_SetString(PyExc_ValueError, "Raise with cause but no exception"); |
816 | return 0; |
817 | } |
818 | ret = 1; |
819 | break; |
820 | case Try_kind: Branch (820:5): [True: 1.47k, False: 68.4k]
|
821 | if (!validate_body(state, stmt->v.Try.body, "Try")) Branch (821:13): [True: 2, False: 1.47k]
|
822 | return 0; |
823 | if (!asdl_seq_LEN(stmt->v.Try.handlers) && Branch (823:13): [True: 152, False: 1.31k]
|
824 | !152 asdl_seq_LEN152 (stmt->v.Try.finalbody)) { Branch (824:13): [True: 1, False: 151]
|
825 | PyErr_SetString(PyExc_ValueError, "Try has neither except handlers nor finalbody"); |
826 | return 0; |
827 | } |
828 | if (!asdl_seq_LEN(stmt->v.Try.handlers) && Branch (828:13): [True: 151, False: 1.31k]
|
829 | asdl_seq_LEN151 (stmt->v.Try.orelse)) { |
830 | PyErr_SetString(PyExc_ValueError, "Try has orelse but no except handlers"); |
831 | return 0; |
832 | } |
833 | for (i = 0; 1.46k i < asdl_seq_LEN(stmt->v.Try.handlers); i++1.39k ) { Branch (833:21): [True: 1.39k, False: 1.46k]
|
834 | excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i); |
835 | VALIDATE_POSITIONS1.39k (handler); |
836 | if ((handler->v.ExceptHandler.type && Branch (836:18): [True: 1.30k, False: 93]
|
837 | !validate_expr(state, handler->v.ExceptHandler.type, Load)1.30k ) || Branch (837:18): [True: 1, False: 1.30k]
|
838 | !validate_body(state, handler->v.ExceptHandler.body, "ExceptHandler")1.39k ) Branch (838:17): [True: 1, False: 1.39k]
|
839 | return 0; |
840 | } |
841 | ret = (!asdl_seq_LEN(stmt->v.Try.finalbody) || Branch (841:16): [True: 1.29k, False: 172]
|
842 | validate_stmts(state, stmt->v.Try.finalbody)172 ) && Branch (842:17): [True: 171, False: 1]
|
843 | (1.46k !1.46k asdl_seq_LEN1.46k (stmt->v.Try.orelse) || Branch (843:14): [True: 1.28k, False: 178]
|
844 | validate_stmts(state, stmt->v.Try.orelse)178 ); Branch (844:14): [True: 177, False: 1]
|
845 | break; |
846 | case TryStar_kind: Branch (846:5): [True: 14, False: 69.9k]
|
847 | if (!validate_body(state, stmt->v.TryStar.body, "TryStar")) Branch (847:13): [True: 2, False: 12]
|
848 | return 0; |
849 | if (!asdl_seq_LEN(stmt->v.TryStar.handlers) && Branch (849:13): [True: 2, False: 10]
|
850 | !2 asdl_seq_LEN2 (stmt->v.TryStar.finalbody)) { Branch (850:13): [True: 1, False: 1]
|
851 | PyErr_SetString(PyExc_ValueError, "TryStar has neither except handlers nor finalbody"); |
852 | return 0; |
853 | } |
854 | if (!asdl_seq_LEN(stmt->v.TryStar.handlers) && Branch (854:13): [True: 1, False: 10]
|
855 | asdl_seq_LEN1 (stmt->v.TryStar.orelse)) { |
856 | PyErr_SetString(PyExc_ValueError, "TryStar has orelse but no except handlers"); |
857 | return 0; |
858 | } |
859 | for (i = 0; 10 i < asdl_seq_LEN(stmt->v.TryStar.handlers); i++9 ) { Branch (859:21): [True: 11, False: 8]
|
860 | excepthandler_ty handler = asdl_seq_GET(stmt->v.TryStar.handlers, i); |
861 | if ((handler->v.ExceptHandler.type && Branch (861:18): [True: 8, False: 3]
|
862 | !validate_expr(state, handler->v.ExceptHandler.type, Load)8 ) || Branch (862:18): [True: 1, False: 7]
|
863 | !validate_body(state, handler->v.ExceptHandler.body, "ExceptHandler")10 ) Branch (863:17): [True: 1, False: 9]
|
864 | return 0; |
865 | } |
866 | ret = (!asdl_seq_LEN(stmt->v.TryStar.finalbody) || Branch (866:16): [True: 6, False: 2]
|
867 | validate_stmts(state, stmt->v.TryStar.finalbody)2 ) && Branch (867:17): [True: 1, False: 1]
|
868 | (7 !7 asdl_seq_LEN7 (stmt->v.TryStar.orelse) || Branch (868:14): [True: 4, False: 3]
|
869 | validate_stmts(state, stmt->v.TryStar.orelse)3 ); Branch (869:14): [True: 2, False: 1]
|
870 | break; |
871 | case Assert_kind: Branch (871:5): [True: 223, False: 69.7k]
|
872 | ret = validate_expr(state, stmt->v.Assert.test, Load) && Branch (872:15): [True: 222, False: 1]
|
873 | (222 !stmt->v.Assert.msg222 || validate_expr(state, stmt->v.Assert.msg, Load)50 ); Branch (873:14): [True: 172, False: 50]
Branch (873:37): [True: 49, False: 1]
|
874 | break; |
875 | case Import_kind: Branch (875:5): [True: 963, False: 68.9k]
|
876 | ret = validate_nonempty_seq(stmt->v.Import.names, "names", "Import"); |
877 | break; |
878 | case ImportFrom_kind: Branch (878:5): [True: 370, False: 69.5k]
|
879 | if (stmt->v.ImportFrom.level < 0) { Branch (879:13): [True: 1, False: 369]
|
880 | PyErr_SetString(PyExc_ValueError, "Negative ImportFrom level"); |
881 | return 0; |
882 | } |
883 | ret = validate_nonempty_seq(stmt->v.ImportFrom.names, "names", "ImportFrom"); |
884 | break; |
885 | case Global_kind: Branch (885:5): [True: 66, False: 69.8k]
|
886 | ret = validate_nonempty_seq(stmt->v.Global.names, "names", "Global"); |
887 | break; |
888 | case Nonlocal_kind: Branch (888:5): [True: 21, False: 69.9k]
|
889 | ret = validate_nonempty_seq(stmt->v.Nonlocal.names, "names", "Nonlocal"); |
890 | break; |
891 | case Expr_kind: Branch (891:5): [True: 12.3k, False: 57.5k]
|
892 | ret = validate_expr(state, stmt->v.Expr.value, Load); |
893 | break; |
894 | case AsyncFunctionDef_kind: Branch (894:5): [True: 41, False: 69.9k]
|
895 | ret = validate_body(state, stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") && Branch (895:15): [True: 41, False: 0]
|
896 | validate_arguments(state, stmt->v.AsyncFunctionDef.args) && Branch (896:13): [True: 41, False: 0]
|
897 | validate_exprs(state, stmt->v.AsyncFunctionDef.decorator_list, Load, 0) && Branch (897:13): [True: 41, False: 0]
|
898 | (!stmt->v.AsyncFunctionDef.returns || Branch (898:14): [True: 41, False: 0]
|
899 | validate_expr(state, stmt->v.AsyncFunctionDef.returns, Load)0 ); Branch (899:14): [True: 0, False: 0]
|
900 | break; |
901 | case Pass_kind: Branch (901:5): [True: 779, False: 69.1k]
|
902 | case Break_kind: Branch (902:5): [True: 358, False: 69.5k]
|
903 | case Continue_kind: Branch (903:5): [True: 266, False: 69.6k]
|
904 | ret = 1; |
905 | break; |
906 | // No default case so compiler emits warning for unhandled cases |
907 | } |
908 | if (ret < 0) { Branch (908:9): [True: 0, False: 69.9k]
|
909 | PyErr_SetString(PyExc_SystemError, "unexpected statement"); |
910 | ret = 0; |
911 | } |
912 | state->recursion_depth--; |
913 | return ret; |
914 | } |
915 | |
916 | static int |
917 | validate_stmts(struct validator *state, asdl_stmt_seq *seq) |
918 | { |
919 | Py_ssize_t i; |
920 | for (i = 0; i < asdl_seq_LEN(seq); i++69.7k ) { Branch (920:17): [True: 69.9k, False: 38.2k]
|
921 | stmt_ty stmt = asdl_seq_GET(seq, i); |
922 | if (stmt) { Branch (922:13): [True: 69.9k, False: 1]
|
923 | if (!validate_stmt(state, stmt)) Branch (923:17): [True: 181, False: 69.7k]
|
924 | return 0; |
925 | } |
926 | else { |
927 | PyErr_SetString(PyExc_ValueError, |
928 | "None disallowed in statement list"); |
929 | return 0; |
930 | } |
931 | } |
932 | return 1; |
933 | } |
934 | |
935 | static int |
936 | validate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ctx, int null_ok) |
937 | { |
938 | Py_ssize_t i; |
939 | for (i = 0; i < asdl_seq_LEN(exprs); i++98.0k ) { Branch (939:17): [True: 98.0k, False: 94.7k]
|
940 | expr_ty expr = asdl_seq_GET(exprs, i); |
941 | if (expr) { Branch (941:13): [True: 98.0k, False: 65]
|
942 | if (!validate_expr(state, expr, ctx)) Branch (942:17): [True: 21, False: 97.9k]
|
943 | return 0; |
944 | } |
945 | else if (!null_ok) { Branch (945:18): [True: 12, False: 53]
|
946 | PyErr_SetString(PyExc_ValueError, |
947 | "None disallowed in expression list"); |
948 | return 0; |
949 | } |
950 | |
951 | } |
952 | return 1; |
953 | } |
954 | |
955 | static int |
956 | validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_ok) |
957 | { |
958 | Py_ssize_t i; |
959 | for (i = 0; i < asdl_seq_LEN(patterns); i++7 ) { Branch (959:17): [True: 15, False: 13]
|
960 | pattern_ty pattern = asdl_seq_GET(patterns, i); |
961 | if (!validate_pattern(state, pattern, star_ok)) { Branch (961:13): [True: 8, False: 7]
|
962 | return 0; |
963 | } |
964 | } |
965 | return 1; |
966 | } |
967 | |
968 | |
969 | /* See comments in symtable.c. */ |
970 | #define COMPILER_STACK_FRAME_SCALE 3 |
971 | |
972 | int |
973 | _PyAST_Validate(mod_ty mod) |
974 | { |
975 | int res = -1; |
976 | struct validator state; |
977 | PyThreadState *tstate; |
978 | int recursion_limit = Py_GetRecursionLimit(); |
979 | int starting_recursion_depth; |
980 | |
981 | /* Setup recursion depth check counters */ |
982 | tstate = _PyThreadState_GET(); |
983 | if (!tstate) { Branch (983:9): [True: 0, False: 679]
|
984 | return 0; |
985 | } |
986 | /* Be careful here to prevent overflow. */ |
987 | int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; |
988 | starting_recursion_depth = (recursion_depth< INT_MAX / COMPILER_STACK_FRAME_SCALE) ? Branch (988:32): [True: 679, False: 0]
|
989 | recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth0 ; |
990 | state.recursion_depth = starting_recursion_depth; |
991 | state.recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? Branch (991:29): [True: 679, False: 0]
|
992 | recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit0 ; |
993 | |
994 | switch (mod->kind) { Branch (994:13): [True: 0, False: 679]
|
995 | case Module_kind: Branch (995:5): [True: 568, False: 111]
|
996 | res = validate_stmts(&state, mod->v.Module.body); |
997 | break; |
998 | case Interactive_kind: Branch (998:5): [True: 2, False: 677]
|
999 | res = validate_stmts(&state, mod->v.Interactive.body); |
1000 | break; |
1001 | case Expression_kind: Branch (1001:5): [True: 109, False: 570]
|
1002 | res = validate_expr(&state, mod->v.Expression.body, Load); |
1003 | break; |
1004 | case FunctionType_kind: Branch (1004:5): [True: 0, False: 679]
|
1005 | res = validate_exprs(&state, mod->v.FunctionType.argtypes, Load, /*null_ok=*/0) && Branch (1005:15): [True: 0, False: 0]
|
1006 | validate_expr(&state, mod->v.FunctionType.returns, Load); Branch (1006:15): [True: 0, False: 0]
|
1007 | break; |
1008 | // No default case so compiler emits warning for unhandled cases |
1009 | } |
1010 | |
1011 | if (res < 0) { Branch (1011:9): [True: 0, False: 679]
|
1012 | PyErr_SetString(PyExc_SystemError, "impossible module node"); |
1013 | return 0; |
1014 | } |
1015 | |
1016 | /* Check that the recursion depth counting balanced correctly */ |
1017 | if (res && state.recursion_depth != starting_recursion_depth502 ) { Branch (1017:9): [True: 502, False: 177]
Branch (1017:16): [True: 0, False: 502]
|
1018 | PyErr_Format(PyExc_SystemError, |
1019 | "AST validator recursion depth mismatch (before=%d, after=%d)", |
1020 | starting_recursion_depth, state.recursion_depth); |
1021 | return 0; |
1022 | } |
1023 | return res; |
1024 | } |
1025 | |
1026 | PyObject * |
1027 | _PyAST_GetDocString(asdl_stmt_seq *body) |
1028 | { |
1029 | if (!asdl_seq_LEN(body)) { Branch (1029:9): [True: 600, False: 98.3k]
|
1030 | return NULL; |
1031 | } |
1032 | stmt_ty st = asdl_seq_GET(body, 0); |
1033 | if (st->kind != Expr_kind) { Branch (1033:9): [True: 72.1k, False: 26.1k]
|
1034 | return NULL; |
1035 | } |
1036 | expr_ty e = st->v.Expr.value; |
1037 | if (e->kind == Constant_kind && PyUnicode_CheckExact13.1k (e->v.Constant.value)) { Branch (1037:9): [True: 13.1k, False: 12.9k]
|
1038 | return e->v.Constant.value; |
1039 | } |
1040 | return NULL; |
1041 | } |