Skip to content

Commit 9498806

Browse files
committed
Add new parser error code, E_OVERFLOW. This error is returned when
the number of children of a node exceeds the max possible value for the short that is used to count them. The Python runtime converts this parser error into the SyntaxError "expression too long."
1 parent 56c807d commit 9498806

File tree

5 files changed

+28
-18
lines changed

5 files changed

+28
-18
lines changed

Include/errcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ PERFORMANCE OF THIS SOFTWARE.
5252
#define E_DONE 16 /* Parsing complete */
5353
#define E_ERROR 17 /* Execution error */
5454
#define E_INDENT 18 /* Invalid indentation detected */
55+
#define E_OVERFLOW 19 /* Node had too many children */
5556

5657
#ifdef __cplusplus
5758
}

Include/node.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ typedef struct _node {
4646
} node;
4747

4848
extern DL_IMPORT(node *) PyNode_New Py_PROTO((int type));
49-
extern DL_IMPORT(node *) PyNode_AddChild Py_PROTO((node *n, int type, char *str, int lineno));
49+
extern DL_IMPORT(int) PyNode_AddChild Py_PROTO((node *n, int type, char *str, int lineno));
5050
extern DL_IMPORT(void) PyNode_Free Py_PROTO((node *n));
5151

5252
/* Node access functions */

Parser/node.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ PERFORMANCE OF THIS SOFTWARE.
2929
3030
******************************************************************/
3131

32+
#include <limits.h>
33+
3234
/* Parse tree node implementation */
3335

3436
#include "pgenheaders.h"
3537
#include "node.h"
38+
#include "errcode.h"
3639

3740
node *
3841
PyNode_New(type)
@@ -52,7 +55,7 @@ PyNode_New(type)
5255
#define XXX 3 /* Node alignment factor to speed up realloc */
5356
#define XXXROUNDUP(n) ((n) == 1 ? 1 : ((n) + XXX - 1) / XXX * XXX)
5457

55-
node *
58+
int
5659
PyNode_AddChild(n1, type, str, lineno)
5760
register node *n1;
5861
int type;
@@ -62,12 +65,14 @@ PyNode_AddChild(n1, type, str, lineno)
6265
register int nch = n1->n_nchildren;
6366
register int nch1 = nch+1;
6467
register node *n;
68+
if (nch == SHRT_MAX || nch < 0)
69+
return E_OVERFLOW;
6570
if (XXXROUNDUP(nch) < nch1) {
6671
n = n1->n_child;
6772
nch1 = XXXROUNDUP(nch1);
6873
PyMem_RESIZE(n, node, nch1);
6974
if (n == NULL)
70-
return NULL;
75+
return E_NOMEM;
7176
n1->n_child = n;
7277
}
7378
n = &n1->n_child[n1->n_nchildren++];
@@ -76,7 +81,7 @@ PyNode_AddChild(n1, type, str, lineno)
7681
n->n_lineno = lineno;
7782
n->n_nchildren = 0;
7883
n->n_child = NULL;
79-
return n;
84+
return 0;
8085
}
8186

8287
/* Forward */

Parser/parser.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,11 @@ shift(s, type, str, newstate, lineno)
153153
int newstate;
154154
int lineno;
155155
{
156+
int err;
156157
assert(!s_empty(s));
157-
if (PyNode_AddChild(s->s_top->s_parent, type, str, lineno) == NULL) {
158-
fprintf(stderr, "shift: no mem in addchild\n");
159-
return -1;
160-
}
158+
err = PyNode_AddChild(s->s_top->s_parent, type, str, lineno);
159+
if (err)
160+
return err;
161161
s->s_top->s_state = newstate;
162162
return 0;
163163
}
@@ -172,13 +172,13 @@ push(s, type, d, newstate, lineno)
172172
int newstate;
173173
int lineno;
174174
{
175+
int err;
175176
register node *n;
176177
n = s->s_top->s_parent;
177178
assert(!s_empty(s));
178-
if (PyNode_AddChild(n, type, (char *)NULL, lineno) == NULL) {
179-
fprintf(stderr, "push: no mem in addchild\n");
180-
return -1;
181-
}
179+
err = PyNode_AddChild(n, type, (char *)NULL, lineno);
180+
if (err)
181+
return err;
182182
s->s_top->s_state = newstate;
183183
return s_push(s, d, CHILD(n, NCH(n)-1));
184184
}
@@ -233,6 +233,7 @@ PyParser_AddToken(ps, type, str, lineno)
233233
int lineno;
234234
{
235235
register int ilabel;
236+
int err;
236237

237238
D(printf("Token %s/'%s' ... ", _PyParser_TokenNames[type], str));
238239

@@ -260,20 +261,20 @@ PyParser_AddToken(ps, type, str, lineno)
260261
int arrow = x & ((1<<7)-1);
261262
dfa *d1 = PyGrammar_FindDFA(
262263
ps->p_grammar, nt);
263-
if (push(&ps->p_stack, nt, d1,
264-
arrow, lineno) < 0) {
264+
if ((err = push(&ps->p_stack, nt, d1,
265+
arrow, lineno)) > 0) {
265266
D(printf(" MemError: push\n"));
266-
return E_NOMEM;
267+
return err;
267268
}
268269
D(printf(" Push ...\n"));
269270
continue;
270271
}
271272

272273
/* Shift the token */
273-
if (shift(&ps->p_stack, type, str,
274-
x, lineno) < 0) {
274+
if ((err = shift(&ps->p_stack, type, str,
275+
x, lineno)) > 0) {
275276
D(printf(" MemError: shift.\n"));
276-
return E_NOMEM;
277+
return err;
277278
}
278279
D(printf(" Shift.\n"));
279280
/* Pop while we are in an accept-only state */

Python/pythonrun.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,9 @@ err_input(err)
10331033
case E_INDENT:
10341034
msg = "inconsistent use of tabs and spaces in indentation";
10351035
break;
1036+
case E_OVERFLOW:
1037+
msg = "expression too long";
1038+
break;
10361039
default:
10371040
fprintf(stderr, "error=%d\n", err->error);
10381041
msg = "unknown parsing error";

0 commit comments

Comments
 (0)