From patchwork Fri Jun 1 10:25:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 10442945 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 898B1601D3 for ; Fri, 1 Jun 2018 10:25:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 74BE528D7B for ; Fri, 1 Jun 2018 10:25:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6772028D8B; Fri, 1 Jun 2018 10:25:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D455A28D7B for ; Fri, 1 Jun 2018 10:25:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751068AbeFAKZc (ORCPT ); Fri, 1 Jun 2018 06:25:32 -0400 Received: from orcrist.hmeau.com ([104.223.48.154]:57752 "EHLO deadmen.hmeau.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750793AbeFAKZb (ORCPT ); Fri, 1 Jun 2018 06:25:31 -0400 Received: from gondobar.mordor.me.apana.org.au ([192.168.128.4] helo=gondobar) by deadmen.hmeau.com with esmtps (Exim 4.89 #2 (Debian)) id 1fOhFS-0002nB-Ji; Fri, 01 Jun 2018 18:25:30 +0800 Received: from herbert by gondobar with local (Exim 4.89) (envelope-from ) id 1fOhFR-000876-KG; Fri, 01 Jun 2018 18:25:29 +0800 Date: Fri, 1 Jun 2018 18:25:29 +0800 From: Herbert Xu To: Jilles Tjoelker Cc: DASH Mailing List Subject: [v3 PATCH] expand: Ensure result is escaped in cvtnum Message-ID: <20180601102529.aq2hdwpyf546fgtf@gondor.apana.org.au> References: <20180527162200.fpierwhpnaurv3lj@gondor.apana.org.au> <20180528180026.5bavr7djzsrybbig@gondor.apana.org.au> <20180531200250.GA1370@stack.nl> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20180531200250.GA1370@stack.nl> User-Agent: NeoMutt/20170113 (1.7.2) Sender: dash-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dash@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Thu, May 31, 2018 at 10:02:50PM +0200, Jilles Tjoelker wrote: > > This negation overflows if result is INTMAX_MIN, leading to undefined > behaviour. Perhaps leave the memtodest call but use STADJUST to remove > the minus sign itself, leaving only the CTLESC or nothing. Good point. However this turned out to be very messy so let's just bite the bullet and make cvtnum always scan the whole string even though it's not necessary in the other cases (the values being always non-negative). ---8<--- The minus sign generated from arithmetic expansion is currently unquoted which causes anomalies when the result is used in where the quoting matters. This patch fixes it by explicitly calling memtodest on the result in cvtnum. Signed-off-by: Herbert Xu diff --git a/src/expand.c b/src/expand.c index 67350ad..14daa63 100644 --- a/src/expand.c +++ b/src/expand.c @@ -116,7 +116,7 @@ static char *expari(char *start, int flag); STATIC void expbackq(union node *, int); STATIC char *evalvar(char *, int); static size_t strtodest(const char *p, int flags); -static void memtodest(const char *p, size_t len, int flags); +static size_t memtodest(const char *p, size_t len, int flags); STATIC ssize_t varvalue(char *, int, int, int); STATIC void expandmeta(struct strlist *, int); #ifdef HAVE_GLOB @@ -133,7 +133,7 @@ STATIC int pmatch(const char *, const char *); #else #define pmatch(a, b) !fnmatch((a), (b), 0) #endif -static int cvtnum(intmax_t num, int flags); +static size_t cvtnum(intmax_t num, int flags); STATIC size_t esclen(const char *, const char *); STATIC char *scanleft(char *, char *, char *, char *, int, int); STATIC char *scanright(char *, char *, char *, char *, int, int); @@ -795,15 +795,17 @@ record: * Put a string on the stack. */ -static void memtodest(const char *p, size_t len, int flags) +static size_t memtodest(const char *p, size_t len, int flags) { const char *syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX; char *q; + char *s; if (unlikely(!len)) - return; + return 0; q = makestrspace(len * 2, expdest); + s = q; do { int c = (signed char)*p++; @@ -818,6 +820,7 @@ static void memtodest(const char *p, size_t len, int flags) } while (--len); expdest = q; + return q - s; } @@ -1711,14 +1714,13 @@ casematch(union node *pattern, char *val) * Our own itoa(). */ -static int cvtnum(intmax_t num, int flags) +static size_t cvtnum(intmax_t num, int flags) { int len = max_int_length(sizeof(num)); char buf[len]; len = fmtstr(buf, len, "%" PRIdMAX, num); - memtodest(buf, len, flags); - return len; + return memtodest(buf, len, flags); } STATIC void