From patchwork Thu Jan 19 21:06:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Michael Greenberg X-Patchwork-Id: 9526895 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 49CCD6020B for ; Thu, 19 Jan 2017 21:13:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3BEEF285DC for ; Thu, 19 Jan 2017 21:13:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3043C2865B; Thu, 19 Jan 2017 21:13:16 +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=-6.9 required=2.0 tests=BAYES_00,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 A51DC285DC for ; Thu, 19 Jan 2017 21:13:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751907AbdASVNP (ORCPT ); Thu, 19 Jan 2017 16:13:15 -0500 Received: from esa2.pomona.iphmx.com ([68.232.143.226]:18098 "EHLO esa2.pomona.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751349AbdASVNG (ORCPT ); Thu, 19 Jan 2017 16:13:06 -0500 X-Greylist: delayed 346 seconds by postgrey-1.27 at vger.kernel.org; Thu, 19 Jan 2017 16:13:06 EST X-IronPort-AV: E=Sophos;i="5.33,255,1477983600"; d="scan'208";a="135512940" Received: from hub1.campus.pomona.edu ([134.173.71.127]) by esa2.pomona.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 19 Jan 2017 13:06:51 -0800 Received: from EXCHANGE9.campus.pomona.edu ([169.254.1.200]) by HUB1.campus.pomona.edu ([134.173.71.127]) with mapi id 14.03.0319.002; Thu, 19 Jan 2017 13:06:51 -0800 From: Michael Greenberg To: "dash@vger.kernel.org" CC: Austin John Blatt Subject: [PATCH] unset/null variables should expand to 0 during arithmetic expansion Thread-Topic: [PATCH] unset/null variables should expand to 0 during arithmetic expansion Thread-Index: AQHScpf0THVbWqxm+Ei/shs27oDeJg== Date: Thu, 19 Jan 2017 21:06:51 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [89.2.141.229] Content-ID: MIME-Version: 1.0 Sender: dash-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dash@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hi, It seems like dash has a subtly incorrect arithmetic expansion for variables that are unset. For example, consider the following program: unset x ; echo $((x+=2)) Running bash on this program echoes the number 2 to standard out and sets x to 2. Running dash (git HEAD/release 0.5.9.1) yields an error: src/dash: 1: Illegal number: Now, bash and dash disagreeing isn’t such a big deal. But it seems like the standard indicates bash’s defaulting is correct for unset variables. According to , “the arithmetic expression shall be processed according to the rules given in Arithmetic Precision and Operations”, which says “all variables shall be initialized to zero if they are not otherwise assigned by the input to the application” . The standard is a little bit unclear about what to do for variables that are set to null (or non-numeric values). I’d interpret the standard as defaulting for unset variables, having null and other non-numeric strings cause some kind of error. bash, as usual, goes well beyond what the standard indicates: any non-numerical value is defaulted to 0. So: x="" ; echo $((x+=2)) x=“yo” ; echo $((x+=2)) both yield 2! If you ask me, that’s a bridge too far—and asking for bugs. I should add that my student (Austin Blatt, CC-ed) noticed this issue; I wrote the attached, single-line fix. Cheers, Michael Signed-off-by: Michael Greenberg — diff --git a/src/var.c b/src/var.c index cc6f7f2..e34f9cf 100644 --- a/src/var.c +++ b/src/var.c @@ -353,7 +353,7 @@ lookupvar(const char *name) intmax_t lookupvarint(const char *name) { - return atomax(lookupvar(name) ?: nullstr, 0); + return atomax(lookupvar(name) ?: "0", 0); }