From 94988067b96c6187fd940eaff99c2c5a68daac68 Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Tue, 20 Jun 2000 19:10:44 +0000 Subject: [PATCH] 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." --- Include/errcode.h | 1 + Include/node.h | 2 +- Parser/node.c | 11 ++++++++--- Parser/parser.c | 29 +++++++++++++++-------------- Python/pythonrun.c | 3 +++ 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Include/errcode.h b/Include/errcode.h index 565578269af..f94c11c02ce 100644 --- a/Include/errcode.h +++ b/Include/errcode.h @@ -52,6 +52,7 @@ PERFORMANCE OF THIS SOFTWARE. #define E_DONE 16 /* Parsing complete */ #define E_ERROR 17 /* Execution error */ #define E_INDENT 18 /* Invalid indentation detected */ +#define E_OVERFLOW 19 /* Node had too many children */ #ifdef __cplusplus } diff --git a/Include/node.h b/Include/node.h index 7f30923b5a0..3a564f78213 100644 --- a/Include/node.h +++ b/Include/node.h @@ -46,7 +46,7 @@ typedef struct _node { } node; extern DL_IMPORT(node *) PyNode_New Py_PROTO((int type)); -extern DL_IMPORT(node *) PyNode_AddChild Py_PROTO((node *n, int type, char *str, int lineno)); +extern DL_IMPORT(int) PyNode_AddChild Py_PROTO((node *n, int type, char *str, int lineno)); extern DL_IMPORT(void) PyNode_Free Py_PROTO((node *n)); /* Node access functions */ diff --git a/Parser/node.c b/Parser/node.c index c2308fddee7..3f593c8fde3 100644 --- a/Parser/node.c +++ b/Parser/node.c @@ -29,10 +29,13 @@ PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ +#include + /* Parse tree node implementation */ #include "pgenheaders.h" #include "node.h" +#include "errcode.h" node * PyNode_New(type) @@ -52,7 +55,7 @@ PyNode_New(type) #define XXX 3 /* Node alignment factor to speed up realloc */ #define XXXROUNDUP(n) ((n) == 1 ? 1 : ((n) + XXX - 1) / XXX * XXX) -node * +int PyNode_AddChild(n1, type, str, lineno) register node *n1; int type; @@ -62,12 +65,14 @@ PyNode_AddChild(n1, type, str, lineno) register int nch = n1->n_nchildren; register int nch1 = nch+1; register node *n; + if (nch == SHRT_MAX || nch < 0) + return E_OVERFLOW; if (XXXROUNDUP(nch) < nch1) { n = n1->n_child; nch1 = XXXROUNDUP(nch1); PyMem_RESIZE(n, node, nch1); if (n == NULL) - return NULL; + return E_NOMEM; n1->n_child = n; } n = &n1->n_child[n1->n_nchildren++]; @@ -76,7 +81,7 @@ PyNode_AddChild(n1, type, str, lineno) n->n_lineno = lineno; n->n_nchildren = 0; n->n_child = NULL; - return n; + return 0; } /* Forward */ diff --git a/Parser/parser.c b/Parser/parser.c index 3b75dbc3f4d..00299afe70c 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -153,11 +153,11 @@ shift(s, type, str, newstate, lineno) int newstate; int lineno; { + int err; assert(!s_empty(s)); - if (PyNode_AddChild(s->s_top->s_parent, type, str, lineno) == NULL) { - fprintf(stderr, "shift: no mem in addchild\n"); - return -1; - } + err = PyNode_AddChild(s->s_top->s_parent, type, str, lineno); + if (err) + return err; s->s_top->s_state = newstate; return 0; } @@ -172,13 +172,13 @@ push(s, type, d, newstate, lineno) int newstate; int lineno; { + int err; register node *n; n = s->s_top->s_parent; assert(!s_empty(s)); - if (PyNode_AddChild(n, type, (char *)NULL, lineno) == NULL) { - fprintf(stderr, "push: no mem in addchild\n"); - return -1; - } + err = PyNode_AddChild(n, type, (char *)NULL, lineno); + if (err) + return err; s->s_top->s_state = newstate; return s_push(s, d, CHILD(n, NCH(n)-1)); } @@ -233,6 +233,7 @@ PyParser_AddToken(ps, type, str, lineno) int lineno; { register int ilabel; + int err; D(printf("Token %s/'%s' ... ", _PyParser_TokenNames[type], str)); @@ -260,20 +261,20 @@ PyParser_AddToken(ps, type, str, lineno) int arrow = x & ((1<<7)-1); dfa *d1 = PyGrammar_FindDFA( ps->p_grammar, nt); - if (push(&ps->p_stack, nt, d1, - arrow, lineno) < 0) { + if ((err = push(&ps->p_stack, nt, d1, + arrow, lineno)) > 0) { D(printf(" MemError: push\n")); - return E_NOMEM; + return err; } D(printf(" Push ...\n")); continue; } /* Shift the token */ - if (shift(&ps->p_stack, type, str, - x, lineno) < 0) { + if ((err = shift(&ps->p_stack, type, str, + x, lineno)) > 0) { D(printf(" MemError: shift.\n")); - return E_NOMEM; + return err; } D(printf(" Shift.\n")); /* Pop while we are in an accept-only state */ diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 77607146546..3a60e472466 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1033,6 +1033,9 @@ err_input(err) case E_INDENT: msg = "inconsistent use of tabs and spaces in indentation"; break; + case E_OVERFLOW: + msg = "expression too long"; + break; default: fprintf(stderr, "error=%d\n", err->error); msg = "unknown parsing error";