All of lore.kernel.org
 help / color / mirror / Atom feed
From: Herbert Xu <herbert@gondor.apana.org.au>
To: Jilles Tjoelker <jilles@stack.nl>, Eric Blake <eblake@redhat.com>,
	Oleg Bulatov <oleg@bulatov.me>,
	dash@vger.kernel.org, Juergen Daubert <jue@jue.li>
Subject: [PATCH 4/4] input: Allow two consecutive calls to pungetc
Date: Mon, 05 Jan 2015 23:01:56 +1100	[thread overview]
Message-ID: <E1Y86M8-0001nI-D5@gondolin.me.apana.org.au> (raw)
In-Reply-To: 20150105120030.GA6101@gondor.apana.org.au

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@stack.nl>
Reported-by: Juergen Daubert <jue@jue.li>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 src/input.c |   30 ++++++++++++++++++++++--------
 src/input.h |   12 ++++++++++++
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/src/input.c b/src/input.c
index 6223a73..06c08d4 100644
--- a/src/input.c
+++ b/src/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/src/input.h b/src/input.h
index ad8b463..ec97c1d 100644
--- a/src/input.h
+++ b/src/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;

      parent reply	other threads:[~2015-01-05 12:02 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-26 12:15 Line continuation and variables Oleg Bulatov
2014-08-26 12:34 ` Eric Blake
2014-09-29 14:55   ` Herbert Xu
2014-09-29 14:57     ` Herbert Xu
2014-10-29 21:52     ` Jilles Tjoelker
2014-10-30  2:10       ` Herbert Xu
2015-01-05 12:00       ` [0/4] input: Allow two consecutive calls to pungetc Herbert Xu
2015-01-05 12:01         ` [PATCH 1/4] input: Make preadbuffer static Herbert Xu
2015-01-05 12:01         ` [PATCH 2/4] input: Remove HETIO Herbert Xu
2015-01-05 12:01         ` [PATCH 3/4] input: Move all input state into parsefile Herbert Xu
2015-01-05 12:01         ` Herbert Xu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E1Y86M8-0001nI-D5@gondolin.me.apana.org.au \
    --to=herbert@gondor.apana.org.au \
    --cc=dash@vger.kernel.org \
    --cc=eblake@redhat.com \
    --cc=jilles@stack.nl \
    --cc=jue@jue.li \
    --cc=oleg@bulatov.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.