mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	bpo-37947: Avoid double-decrement in symtable recursion counting (GH-15593)
With `symtable_visit_expr` now correctly adjusting the recursion depth for named expressions, `symtable_handle_namedexpr` should be leaving it alone. Also adds a new check to `PySymtable_BuildObject` that raises `SystemError` if a successful first symbol analysis pass fails to keep the stack depth accounting clean.
This commit is contained in:
		
							parent
							
								
									2c5fb17118
								
							
						
					
					
						commit
						06145230c8
					
				
					 1 changed files with 14 additions and 4 deletions
				
			
		| 
						 | 
					@ -266,6 +266,7 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    PyThreadState *tstate;
 | 
					    PyThreadState *tstate;
 | 
				
			||||||
    int recursion_limit = Py_GetRecursionLimit();
 | 
					    int recursion_limit = Py_GetRecursionLimit();
 | 
				
			||||||
 | 
					    int starting_recursion_depth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (st == NULL)
 | 
					    if (st == NULL)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
| 
						 | 
					@ -284,8 +285,9 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /* Be careful here to prevent overflow. */
 | 
					    /* Be careful here to prevent overflow. */
 | 
				
			||||||
    st->recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
 | 
					    starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
 | 
				
			||||||
        tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth;
 | 
					        tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth;
 | 
				
			||||||
 | 
					    st->recursion_depth = starting_recursion_depth;
 | 
				
			||||||
    st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
 | 
					    st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
 | 
				
			||||||
        recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit;
 | 
					        recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -329,6 +331,14 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
 | 
				
			||||||
        PySymtable_Free(st);
 | 
					        PySymtable_Free(st);
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /* Check that the recursion depth counting balanced correctly */
 | 
				
			||||||
 | 
					    if (st->recursion_depth != starting_recursion_depth) {
 | 
				
			||||||
 | 
					        PyErr_Format(PyExc_SystemError,
 | 
				
			||||||
 | 
					            "symtable analysis recursion depth mismatch (before=%d, after=%d)",
 | 
				
			||||||
 | 
					            starting_recursion_depth, st->recursion_depth);
 | 
				
			||||||
 | 
					        PySymtable_Free(st);
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /* Make the second symbol analysis pass */
 | 
					    /* Make the second symbol analysis pass */
 | 
				
			||||||
    if (symtable_analyze(st))
 | 
					    if (symtable_analyze(st))
 | 
				
			||||||
        return st;
 | 
					        return st;
 | 
				
			||||||
| 
						 | 
					@ -1501,16 +1511,16 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e)
 | 
				
			||||||
        PyErr_SyntaxLocationObject(st->st_filename,
 | 
					        PyErr_SyntaxLocationObject(st->st_filename,
 | 
				
			||||||
                                    e->lineno,
 | 
					                                    e->lineno,
 | 
				
			||||||
                                    e->col_offset);
 | 
					                                    e->col_offset);
 | 
				
			||||||
        VISIT_QUIT(st, 0);
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (st->st_cur->ste_comprehension) {
 | 
					    if (st->st_cur->ste_comprehension) {
 | 
				
			||||||
        /* Inside a comprehension body, so find the right target scope */
 | 
					        /* Inside a comprehension body, so find the right target scope */
 | 
				
			||||||
        if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target))
 | 
					        if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target))
 | 
				
			||||||
            VISIT_QUIT(st, 0);
 | 
					            return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    VISIT(st, expr, e->v.NamedExpr.value);
 | 
					    VISIT(st, expr, e->v.NamedExpr.value);
 | 
				
			||||||
    VISIT(st, expr, e->v.NamedExpr.target);
 | 
					    VISIT(st, expr, e->v.NamedExpr.target);
 | 
				
			||||||
    VISIT_QUIT(st, 1);
 | 
					    return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue