klibc-bot for Herbert Xu
2019-Jan-25 03:15 UTC
[klibc] [klibc:update-dash] input: Allow two consecutive calls to pungetc
Commit-ID: 39d9f472762cd928024a5cb836aef46f14031756 Gitweb: http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=39d9f472762cd928024a5cb836aef46f14031756 Author: Herbert Xu <herbert at gondor.apana.org.au> AuthorDate: Mon, 5 Jan 2015 22:50:57 +1100 Committer: Ben Hutchings <ben at decadent.org.uk> CommitDate: Fri, 25 Jan 2019 02:57:21 +0000 [klibc] input: Allow two consecutive calls to pungetc The commit ef91d3d6a4c39421fd3a391e02cd82f9f3aee4a8 ([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 at stack.nl> Reported-by: Juergen Daubert <jue at jue.li> Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au> Signed-off-by: Ben Hutchings <ben at decadent.org.uk> --- usr/dash/input.c | 30 ++++++++++++++++++++++-------- usr/dash/input.h | 12 ++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/usr/dash/input.c b/usr/dash/input.c index 6223a735..06c08d49 100644 --- a/usr/dash/input.c +++ b/usr/dash/input.c @@ -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; } @@ -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 && @@ -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)) @@ -290,15 +299,14 @@ again: } /* - * 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++; } /* @@ -322,6 +330,8 @@ 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; @@ -329,6 +339,7 @@ pushstring(char *s, void *ap) } parsefile->nextc = s; parsefile->nleft = len; + parsefile->unget = 0; INTON; } @@ -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)) @@ -439,6 +452,7 @@ pushfile(void) pf->fd = -1; pf->strpush = NULL; pf->basestrpush.prev = NULL; + pf->unget = 0; parsefile = pf; } diff --git a/usr/dash/input.h b/usr/dash/input.h index ad8b463d..ec97c1d6 100644 --- a/usr/dash/input.h +++ b/usr/dash/input.h @@ -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; }; /* @@ -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;
Possibly Parallel Threads
- [klibc:update-dash] dash: input: Allow two consecutive calls to pungetc
- [klibc:update-dash] input: Move all input state into parsefile
- [klibc:update-dash] dash: input: Move all input state into parsefile
- [klibc:update-dash] [PARSER] Removed unnecessary pungetc on EOF from parser
- [klibc:update-dash] dash: [PARSER] Removed unnecessary pungetc on EOF from parser