NetBSD Problem Report #57997

From www@netbsd.org  Mon Mar  4 18:26:09 2024
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 34A6A1A9239
	for <gnats-bugs@gnats.NetBSD.org>; Mon,  4 Mar 2024 18:26:09 +0000 (UTC)
Message-Id: <20240304182607.C94021A923A@mollari.NetBSD.org>
Date: Mon,  4 Mar 2024 18:26:07 +0000 (UTC)
From: rvp@SDF.ORG
Reply-To: rvp@SDF.ORG
To: gnats-bugs@NetBSD.org
Subject: sh(1) allows an empty list in if statements
X-Send-Pr-Version: www-1.0

>Number:         57997
>Category:       bin
>Synopsis:       sh(1) allows an empty list in if statements
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    bin-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Mar 04 18:30:01 +0000 2024
>Closed-Date:    Mon Mar 11 22:26:08 +0000 2024
>Last-Modified:  Mon Mar 11 22:26:08 +0000 2024
>Originator:     RVP
>Release:        NetBSD-10.99.10
>Organization:
>Environment:
NetBSD CoreBook.local 10.99.10 NetBSD 10.99.10 (MYKERNEL) #0: Sun Mar  3 03:37:44 UTC 2024  bld@CoreBook.local:/tmp/obj/usr/src/sys/arch/amd64/compile/MYKERNEL amd64
>Description:
Apparently, NetBSD's sh(1) doesn't need a `list' after `then' in `if'
statements:

```
#!/bin/sh

if      false
then
elif    false
then
else
fi
echo "Should not reach this!"
```

NetBSD's /bin/sh first here, then some other shells:

```
$ ./then.sh
Should not reach this!

$ bash ./then.sh
./then.sh: line 5: syntax error near unexpected token `elif'
./then.sh: line 5: `elif        false'

$ ksh ./then.sh
./then.sh[5]: syntax error: `elif' unexpected
./then.sh[5]: 

$ ksh93 ./then.sh
./then.sh: syntax error at line 5: `elif' unexpected

$ dash ./then.sh
./then.sh: 5: Syntax error: "elif" unexpected

```

This is the case even in NetBSD 9.3. Haven't checked 8.x. First noticed
in the rehash() function of /usr/sbin/certctl.
>How-To-Repeat:
As above.
>Fix:
No clue.

>Release-Note:

>Audit-Trail:
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57997 CVS commit: src/usr.sbin/certctl
Date: Mon, 4 Mar 2024 20:37:32 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Mar  4 20:37:32 UTC 2024

 Modified Files:
 	src/usr.sbin/certctl: certctl.sh

 Log Message:
 certctl(8): Pacify formal POSIX sh syntax.

 According to POSIX 2018, the syntax between `then' and `elif' and
 `fi' must be a _non-empty_ list of commands:

 compound_list    : linebreak term
                  | linebreak term separator
                  ;
 ...
 if_clause        : If compound_list Then compound_list else_part Fi
                  | If compound_list Then compound_list           Fi
                  ;
 else_part        : Elif compound_list Then compound_list
                  | Elif compound_list Then compound_list else_part
                  | Else compound_list
                  ;

 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10_02

 NetBSD's sh(1) currently doesn't enforce this and allows an empty
 sequence of commands, but let's not rely on that nonstandard quirk.

 Noted in PR 57997.


 To generate a diff of this commit:
 cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/certctl/certctl.sh

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: bin/57997: sh(1) allows an empty list in if statements
Date: Tue, 05 Mar 2024 04:32:59 +0700

     Date:        Mon,  4 Mar 2024 18:30:01 +0000 (UTC)
     From:        rvp@SDF.ORG
     Message-ID:  <20240304183001.9C7081A923B@mollari.NetBSD.org>

   | Apparently, NetBSD's sh(1) doesn't need a `list' after `then' in `if'
   | statements:

 It is ancient histiric ash shell behaviour to allow empty lists
 in places where the standard requires something - the FreeBSD
 shell (or the slightly old version I have anyway) is similar,
 though it looks like dash has been changed.

 There used to be a lot of that, some of it has been altered,
 others left to allow an empty list.

 This is really OK, it is just an extension to the standardm any
 script written to standard shell syntax will never observe it,
 scripts written for the NetBSD shell that want to take advantage
 of the relaxed syntax can do so.   There are very few shells (I'd
 expect probably zero) which have no extensions to the standard
 permitted.

 I'm not inclined to change this unless someone can provide a
 compelling reason why it needs to be changed - if I did change it,
 it would likely only enforce the requirement for something to exist
 there in posix mode.

 kre

From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: bin/57997: sh(1) allows an empty list in if statements
Date: Mon, 4 Mar 2024 22:10:10 +0000 (UTC)

 On Mon, 4 Mar 2024, Robert Elz wrote:

 > I'm not inclined to change this unless someone can provide a
 > compelling reason why it needs to be changed - if I did change it,
 > it would likely only enforce the requirement for something to exist
 > there in posix mode.
 >

 OK, then this PR can be closed. (And the man-page could note that an
 empty `list' is fine after `then' for NetBSD's /bin/sh.)

 Thanks,

 -RVP

From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: bin/57997: sh(1) allows an empty list in if statements
Date: Tue, 05 Mar 2024 06:19:50 +0700

     Date:        Mon,  4 Mar 2024 22:15:02 +0000 (UTC)
     From:        RVP <rvp@SDF.ORG>
     Message-ID:  <20240304221502.A9EC91A923B@mollari.NetBSD.org>

   |  OK, then this PR can be closed.

 Will do.

   | (And the man-page could note that an
   |  empty `list' is fine after `then' for NetBSD's /bin/sh.)

 I don't think that should happen either - this is just ancient
 behaviour that's being retained, not something to be advertised
 as a feature that anyone really ought to be using.

 I think (but don't quote me) that the only place the sh man page
 notes that this is possible, is in function declarations, where
 we allow
 	func() {
 	}
 with no commands in the func body (also not POSIX syntax).  That
 one is deliberate, rather than just retained old code.

 kre

 ps: it isn't just "then":  'if true; then elif then else fi'
 'works' just fine as one like like that, or with interspersed
 newlines.  (I'm not sure why a non-empty command is needed after
 'if' but not after 'elif' ... more historic baggage).

 I suspect some of the reason for this is that the ! command
 (or operator, or whatever that thing really is) did not 
 originally exist, to execute some commands when something failed,
 rather than succeeded (and not using || which isn't always
 appropriate) required (in standard sh syntax)

 	if whatever_test; then : ; else commands_to_run; fi

 and that ':' confused people who weren't sure what it meant.
 I'm guessing (with no real basis for it) that avoiding the
 need for that might be part of (or even wholly) the reason that
 empty commands were allowed (and the other places just get it
 from symmetry).

 Also note that an actual executable command is not needed (in
 POSIX syntax) just something which might be, so

 	E=
 	if whatever_test; then $E ; else commands_to_run; fi

 is perfectly valid POSIX syntax, even though $E is nothing.

State-Changed-From-To: open->closed
State-Changed-By: kre@NetBSD.org
State-Changed-When: Mon, 04 Mar 2024 23:21:54 +0000
State-Changed-Why:
Not a bug, an extension, but ancient compatability, rather than
a desired feature (and consequently, undocumented).


State-Changed-From-To: closed->pending-pullups
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Mon, 11 Mar 2024 01:02:17 +0000
State-Changed-Why:
pullup-10 #625 for the certctl.sh abuse of POSIX syntax
(certctl doesn't exist before netbsd-10)


From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57997 CVS commit: [netbsd-10] src/usr.sbin/certctl
Date: Mon, 11 Mar 2024 17:50:04 +0000

 Module Name:	src
 Committed By:	martin
 Date:		Mon Mar 11 17:50:04 UTC 2024

 Modified Files:
 	src/usr.sbin/certctl [netbsd-10]: certctl.sh

 Log Message:
 Pull up following revision(s) (requested by riastradh in ticket #625):

 	usr.sbin/certctl/certctl.sh: revision 1.7

 certctl(8): Pacify formal POSIX sh syntax.

 According to POSIX 2018, the syntax between `then' and `elif' and
 `fi' must be a _non-empty_ list of commands:
 compound_list    : linebreak term
                  | linebreak term separator
                  ;
 ...
 if_clause        : If compound_list Then compound_list else_part Fi
                  | If compound_list Then compound_list           Fi
                  ;
 else_part        : Elif compound_list Then compound_list
                  | Elif compound_list Then compound_list else_part
                  | Else compound_list
                  ;

 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18
 +_10_02

 NetBSD's sh(1) currently doesn't enforce this and allows an empty
 sequence of commands, but let's not rely on that nonstandard quirk.

 Noted in PR 57997.


 To generate a diff of this commit:
 cvs rdiff -u -r1.4.2.4 -r1.4.2.5 src/usr.sbin/certctl/certctl.sh

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: pending-pullups->closed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Mon, 11 Mar 2024 22:26:08 +0000
State-Changed-Why:
underlying issue not really a problem
certctl(8) abuse of syntax fixed and pulled up


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2024 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.