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