Skip to content

Commit

Permalink
input: Allow two consecutive calls to pungetc
Browse files Browse the repository at this point in the history
The commit ef91d3d ([PARSER]
Handle backslash newlines properly after dollar sign) created
cases where we make two consecutive calls to pungetc.  As we
don't explicitly support that there are corner cases where you
end up with garbage input leading to undefined behaviour.

This patch adds explicit support for two consecutive calls to
pungetc.

Reported-by: Jilles Tjoelker <jilles@stack.nl>
Reported-by: Juergen Daubert <jue@jue.li>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
herbertx committed Jan 5, 2015
1 parent 5178142 commit 17db43b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
30 changes: 22 additions & 8 deletions src/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,20 @@ RESET {
int
pgetc(void)
{
int c;

if (parsefile->unget)
return parsefile->lastc[--parsefile->unget];

if (--parsefile->nleft >= 0)
return (signed char)*parsefile->nextc++;
c = (signed char)*parsefile->nextc++;
else
return preadbuffer();
c = preadbuffer();

parsefile->lastc[1] = parsefile->lastc[0];
parsefile->lastc[0] = c;

return c;
}


Expand Down Expand Up @@ -194,7 +204,7 @@ static int preadbuffer(void)
#endif
char savec;

while (unlikely(parsefile->strpush)) {
if (unlikely(parsefile->strpush)) {
if (
parsefile->nleft == -1 &&
parsefile->strpush->ap &&
Expand All @@ -204,8 +214,7 @@ static int preadbuffer(void)
return PEOA;
}
popstring();
if (--parsefile->nleft >= 0)
return (signed char)*parsefile->nextc++;
return pgetc();
}
if (unlikely(parsefile->nleft == EOF_NLEFT ||
parsefile->buf == NULL))
Expand Down Expand Up @@ -290,15 +299,14 @@ static int preadbuffer(void)
}

/*
* Undo the last call to pgetc. Only one character may be pushed back.
* Undo a call to pgetc. Only two characters may be pushed back.
* PEOF may be pushed back.
*/

void
pungetc(void)
{
parsefile->nleft++;
parsefile->nextc--;
parsefile->unget++;
}

/*
Expand All @@ -322,13 +330,16 @@ pushstring(char *s, void *ap)
sp = parsefile->strpush = &(parsefile->basestrpush);
sp->prevstring = parsefile->nextc;
sp->prevnleft = parsefile->nleft;
sp->unget = parsefile->unget;
memcpy(sp->lastc, parsefile->lastc, sizeof(sp->lastc));
sp->ap = (struct alias *)ap;
if (ap) {
((struct alias *)ap)->flag |= ALIASINUSE;
sp->string = s;
}
parsefile->nextc = s;
parsefile->nleft = len;
parsefile->unget = 0;
INTON;
}

Expand All @@ -353,6 +364,8 @@ popstring(void)
}
parsefile->nextc = sp->prevstring;
parsefile->nleft = sp->prevnleft;
parsefile->unget = sp->unget;
memcpy(parsefile->lastc, sp->lastc, sizeof(sp->lastc));
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
parsefile->strpush = sp->prev;
if (sp != &(parsefile->basestrpush))
Expand Down Expand Up @@ -439,6 +452,7 @@ pushfile(void)
pf->fd = -1;
pf->strpush = NULL;
pf->basestrpush.prev = NULL;
pf->unget = 0;
parsefile = pf;
}

Expand Down
12 changes: 12 additions & 0 deletions src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ struct strpush {
int prevnleft;
struct alias *ap; /* if push was associated with an alias */
char *string; /* remember the string since it may change */

/* Remember last two characters for pungetc. */
int lastc[2];

/* Number of outstanding calls to pungetc. */
int unget;
};

/*
Expand All @@ -66,6 +72,12 @@ struct parsefile {
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
struct strpush basestrpush; /* so pushing one is fast */

/* Remember last two characters for pungetc. */
int lastc[2];

/* Number of outstanding calls to pungetc. */
int unget;
};

extern struct parsefile *parsefile;
Expand Down

0 comments on commit 17db43b

Please sign in to comment.