NetBSD Problem Report #49595

From www@NetBSD.org  Thu Jan 22 04:08:00 2015
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 8F5CEA57FE
	for <gnats-bugs@gnats.NetBSD.org>; Thu, 22 Jan 2015 04:08:00 +0000 (UTC)
Message-Id: <20150122040759.3D46CA6567@mollari.NetBSD.org>
Date: Thu, 22 Jan 2015 04:07:59 +0000 (UTC)
From: william@25thandclement.com
Reply-To: william@25thandclement.com
To: gnats-bugs@NetBSD.org
Subject: unset built-in exits with failure if parameter not set
X-Send-Pr-Version: www-1.0

>Number:         49595
>Category:       bin
>Synopsis:       unset built-in exits with failure if parameter not set
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jan 22 04:10:00 +0000 2015
>Closed-Date:    Tue Oct 11 06:36:15 +0000 2016
>Last-Modified:  Tue Oct 11 06:36:15 +0000 2016
>Originator:     William Ahern
>Release:        6.1.1
>Organization:
>Environment:
NetBSD  6.1.1 NetBSD 6.1.1 (GENERIC) amd6
>Description:
POSIX description of the unset built-in utility says:

"
Unsetting a variable or function that was not previously set shall not be considered an error and does not cause the shell to abort.
"

and

"
EXIT STATUS
0 All name operands were successfully unset.
>0 At least one name could not be unset.
"

While trying to unset a non-existent variable doesn't normally cause the shell to exit (compare PR 47795), the command still exits with a status of 1. So, the shell will exit if strict errors are enabled using set -e or set -o errexit.

NetBSD's /bin/sh is the only shell with this behavior I've found. I've tested /bin/sh on AIX 7, Solaris  11.1, OpenBSD 5.5, OS X 10.2 (BETA), FreeBSD 9.0, and Ubuntu 14.04.

I suppose one could interpret NetBSD's behavior as conforming. But I find it leads to unnecessarily complex code like `unset FOO || true` or `[ "${FOO-unset}" = "unset" ] || unset FOO`

>How-To-Repeat:
Following script should print "OK".

#!/bin/sh
FOO=bar
unset FOO
set -e
unset FOO
printf "OK\n"

>Fix:
Remove the following from c_unset in ksh/c_sh.c:

if (!(vp->flag & ISSET))
        ret = 1;


>Release-Note:

>Audit-Trail:
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/49595: unset built-in exits with failure if parameter not set
Date: Mon, 10 Oct 2016 01:13:00 +0000

 On Thu, Jan 22, 2015 at 04:10:00AM +0000, william@25thandclement.com wrote:
  > NetBSD's /bin/sh is the only shell with this behavior I've
  > found. I've tested /bin/sh on AIX 7, Solaris 11.1, OpenBSD 5.5, OS
  > X 10.2 (BETA), FreeBSD 9.0, and Ubuntu 14.04.
  > 
  > I suppose one could interpret NetBSD's behavior as conforming. But
  > I find it leads to unnecessarily complex code like `unset FOO ||
  > true` or `[ "${FOO-unset}" = "unset" ] || unset FOO`
  > 
  > >How-To-Repeat:
  > Following script should print "OK".
  > 
  > #!/bin/sh
  > FOO=bar
  > unset FOO
  > set -e
  > unset FOO
  > printf "OK\n"

 ok, all this is about sh, but...

  > >Fix:
  > Remove the following from c_unset in ksh/c_sh.c:
  > 
  > if (!(vp->flag & ISSET))
  >         ret = 1;

 ...that's about ksh.

 So are you talking about sh or ksh? Currently, sh does not exhibit
 this behavior, but ksh does.

 -- 
 David A. Holland
 dholland@netbsd.org

State-Changed-From-To: open->feedback
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Mon, 10 Oct 2016 01:44:09 +0000
State-Changed-Why:
I asked a question.


From: William Ahern <william@25thandclement.com>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/49595: unset built-in exits with failure if parameter not set
Date: Mon, 10 Oct 2016 11:22:24 -0700

 On Mon, Oct 10, 2016 at 01:15:00AM +0000, David Holland wrote:
 <snip>
 >  On Thu, Jan 22, 2015 at 04:10:00AM +0000, william@25thandclement.com wrote:
 <snip>
 >   > >How-To-Repeat:
 >   > Following script should print "OK".
 >   > 
 >   > #!/bin/sh
 >   > FOO=bar
 >   > unset FOO
 >   > set -e
 >   > unset FOO
 >   > printf "OK\n"
 >  
 >  ok, all this is about sh, but...
 >  
 >   > >Fix:
 >   > Remove the following from c_unset in ksh/c_sh.c:
 >   > 
 >   > if (!(vp->flag & ISSET))
 >   >         ret = 1;
 >  
 >  ...that's about ksh.
 >  
 >  So are you talking about sh or ksh? Currently, sh does not exhibit
 >  this behavior, but ksh does.

 Oops. I didn't realize /bin/sh and /bin/ksh used different sources, and I
 analyzed and created a patch for the wrong implementation.

 This bug was fixed in sh in revision 1.43

   http://cvsweb.netbsd.org/bsdweb.cgi/src/bin/sh/var.c.diff?r1=1.42&r2=1.43&only_with_tag=MAIN&f=h

 but it never made it into the 6.1 branch. This issue is fixed in 7.0. Sorry
 for the noise.

State-Changed-From-To: feedback->open
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Tue, 11 Oct 2016 06:29:16 +0000
State-Changed-Why:
feedback received, thanks


From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/49595: unset built-in exits with failure if parameter not set
Date: Tue, 11 Oct 2016 06:29:00 +0000

 On Mon, Oct 10, 2016 at 08:10:01PM +0000, William Ahern wrote:
  >  >  So are you talking about sh or ksh? Currently, sh does not exhibit
  >  >  this behavior, but ksh does.
  >  
  >  Oops. I didn't realize /bin/sh and /bin/ksh used different sources, and I
  >  analyzed and created a patch for the wrong implementation.
  >  
  >  This bug was fixed in sh in revision 1.43
  >  
  >    http://cvsweb.netbsd.org/bsdweb.cgi/src/bin/sh/var.c.diff?r1=1.42&r2=1.43&only_with_tag=MAIN&f=h
  >  
  >  but it never made it into the 6.1 branch. This issue is fixed in 7.0. Sorry
  >  for the noise.

 It's not noise :-)  just wanted to be clear on what you meant.

 I filed a request (pullup-6 #1412) to merge this change into the -6
 branch since it's pretty low risk.

 also, since you did the work, may as well fix ksh... although in
 general fixing ksh is rather like trying to bail with an eyedropper.

 -- 
 David A. Holland
 dholland@netbsd.org

From: "David A. Holland" <dholland@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/49595 CVS commit: src/bin/ksh
Date: Tue, 11 Oct 2016 06:31:07 +0000

 Module Name:	src
 Committed By:	dholland
 Date:		Tue Oct 11 06:31:07 UTC 2016

 Modified Files:
 	src/bin/ksh: c_sh.c

 Log Message:
 PR 49595 William Ahern: The exit status of "unset NOTSET" should be 0, not 1.
 (like 48312 but for ksh)


 To generate a diff of this commit:
 cvs rdiff -u -r1.15 -r1.16 src/bin/ksh/c_sh.c

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

State-Changed-From-To: open->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Tue, 11 Oct 2016 06:36:15 +0000
State-Changed-Why:
Fixed in sh in -7, pullup filed for -6 (the change will appear in PR 48312
when it gets handled), fixed in ksh in HEAD too.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.