From patchwork Mon Jan 5 12:01:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 5567281 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: X-Original-To: patchwork-dash@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7DB97BF6C3 for ; Mon, 5 Jan 2015 12:02:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 95C0620172 for ; Mon, 5 Jan 2015 12:02:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1323F20176 for ; Mon, 5 Jan 2015 12:02:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753376AbbAEMCL (ORCPT ); Mon, 5 Jan 2015 07:02:11 -0500 Received: from helcar.apana.org.au ([209.40.204.226]:35813 "EHLO helcar.apana.org.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753370AbbAEMCL (ORCPT ); Mon, 5 Jan 2015 07:02:11 -0500 Received: from gondolin.me.apana.org.au ([192.168.0.6]) by fornost.hengli.com.au with esmtp (Exim 4.80 #3 (Debian)) id 1Y86M8-0005xo-Rq; Mon, 05 Jan 2015 23:01:57 +1100 Received: from herbert by gondolin.me.apana.org.au with local (Exim 4.80) (envelope-from ) id 1Y86M8-0001nI-D5; Mon, 05 Jan 2015 23:01:56 +1100 Subject: [PATCH 4/4] input: Allow two consecutive calls to pungetc References: <20150105120030.GA6101@gondor.apana.org.au> To: Jilles Tjoelker , Eric Blake , Oleg Bulatov , dash@vger.kernel.org, Juergen Daubert Message-Id: From: Herbert Xu Date: Mon, 05 Jan 2015 23:01:56 +1100 Sender: dash-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dash@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reported-by: Juergen Daubert Signed-off-by: Herbert Xu --- src/input.c | 30 ++++++++++++++++++++++-------- src/input.h | 12 ++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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;