@@ -1145,31 +1145,26 @@ try_keyword_typo(Parser *p, KeywordTypo *candidate, KeywordTrial *state)
11451145 // must be private: even a failed trial can memoize nodes containing its edit.
11461146 Token * tokens = PyMem_Malloc (p -> fill * sizeof (* tokens ));
11471147 Token * * index = PyMem_Malloc (p -> fill * sizeof (* index ));
1148- IdentifierCacheEntry * identifiers = p -> identifier_cache == NULL ? NULL :
1149- PyMem_Malloc (IDENTIFIER_CACHE_SIZE * sizeof (* identifiers ));
1148+ Parser trial = * p ;
1149+ trial .identifier_cache = p -> identifier_cache == NULL ? NULL :
1150+ PyMem_Malloc (IDENTIFIER_CACHE_SIZE * sizeof (* trial .identifier_cache ));
11501151 PyArena * arena = _PyArena_New ();
11511152 PyObject * replacement = PyBytes_FromString (candidate -> keyword );
1153+ int accepted = -1 ;
11521154 if (tokens == NULL || index == NULL || arena == NULL || replacement == NULL ||
1153- (p -> identifier_cache != NULL && identifiers == NULL ))
1155+ (p -> identifier_cache != NULL && trial . identifier_cache == NULL ))
11541156 {
1155- PyMem_Free (tokens );
1156- PyMem_Free (index );
1157- PyMem_Free (identifiers );
1158- if (arena != NULL ) {
1159- _PyArena_Free (arena );
1160- }
1161- Py_XDECREF (replacement );
1162- return -1 ;
1157+ goto done ;
11631158 }
11641159 for (int i = 0 ; i < p -> fill ; i ++ ) {
11651160 tokens [i ] = * p -> tokens [i ];
11661161 tokens [i ].memo = NULL ;
11671162 tokens [i ].memo_mask = 0 ;
11681163 index [i ] = & tokens [i ];
11691164 }
1170- if (identifiers != NULL ) {
1171- memcpy (identifiers , p -> identifier_cache ,
1172- IDENTIFIER_CACHE_SIZE * sizeof (* identifiers ));
1165+ if (trial . identifier_cache != NULL ) {
1166+ memcpy (trial . identifier_cache , p -> identifier_cache ,
1167+ IDENTIFIER_CACHE_SIZE * sizeof (* trial . identifier_cache ));
11731168 }
11741169 Token * edited = & tokens [candidate -> mark ];
11751170 edited -> type = _get_keyword_or_name_type (
@@ -1178,7 +1173,6 @@ try_keyword_typo(Parser *p, KeywordTypo *candidate, KeywordTrial *state)
11781173
11791174 state -> furthest = 0 ;
11801175 state -> incomplete_suite = 0 ;
1181- Parser trial = * p ;
11821176 trial .tokens = index ;
11831177 trial .arena = arena ;
11841178 trial .size = trial .fill ;
@@ -1197,10 +1191,9 @@ try_keyword_typo(Parser *p, KeywordTypo *candidate, KeywordTrial *state)
11971191#endif
11981192 trial .known_err_token = NULL ;
11991193 trial .errcode = NULL ;
1200- trial .identifier_cache = identifiers ;
12011194 trial .normalize = NULL ;
1202- int accepted = _PyPegen_parse (& trial ) != NULL &&
1203- !trial .error_indicator && !PyErr_Occurred ();
1195+ accepted = _PyPegen_parse (& trial ) != NULL &&
1196+ !trial .error_indicator && !PyErr_Occurred ();
12041197 for (int i = trial .mark ; accepted && i < trial .fill ; i ++ ) {
12051198 accepted = tokens [i ].type == NEWLINE || tokens [i ].type == ENDMARKER ;
12061199 }
@@ -1224,11 +1217,14 @@ try_keyword_typo(Parser *p, KeywordTypo *candidate, KeywordTrial *state)
12241217 // older grammars, require a complete repair so those checks execute.
12251218 accepted = state -> incomplete_suite && p -> feature_version == PY_MINOR_VERSION ;
12261219 }
1220+ done :
12271221 // No Parser_Free: the trial borrows the tokenizer and type-ignore comments,
12281222 // and its token headers are a single allocation.
12291223 PyMem_Free (trial .identifier_cache );
1230- _PyArena_Free (arena );
1231- Py_DECREF (replacement );
1224+ if (arena != NULL ) {
1225+ _PyArena_Free (arena );
1226+ }
1227+ Py_XDECREF (replacement );
12321228 PyMem_Free (index );
12331229 PyMem_Free (tokens );
12341230 return PyErr_Occurred () ? -1 : accepted ;
@@ -1365,7 +1361,7 @@ keyword_typo_metadata(Parser *p, PySyntaxErrorObject *error)
13651361 qsort (candidates , count , sizeof (* candidates ), compare_keyword_typos );
13661362 // All candidates and both parser passes share this work budget.
13671363 KeywordTrial state = {.budget = MAX_KEYWORD_TYPO_STEPS };
1368- for (int i = 0 ; i < count ; i ++ ) {
1364+ for (int i = 0 ; i < count && state . budget > 0 ; i ++ ) {
13691365 int accepted = try_keyword_typo (p , & candidates [i ], & state );
13701366 if (accepted < 0 ) {
13711367 return NULL ;
0 commit comments