misc/127370: sh -c 'exit -1' fails with "Illegal number: -1", instead of exiting with a code of 255

Andrei Lavreniyuk andy.lavr at reactor-xg.kiev.ua
Sun Sep 14 05:20:02 UTC 2008


>Number:         127370
>Category:       misc
>Synopsis:       sh -c 'exit -1' fails with "Illegal number: -1", instead of exiting with a code of 255
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Sep 14 05:20:01 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Andrei Lavreniyuk
>Release:        7.1-PRERELEASE
>Organization:
Technica-03, Inc.
>Environment:
FreeBSD datacenter.technica-03.local 7.1-PRERELEASE FreeBSD 7.1-PRERELEASE #0: Fri Sep 12 21:28:43 UTC 2008     root at datacenter.technica-03.local:/usr/obj/usr/src/sys/SMP-DATACENTER  i386
>Description:

(c) Garrett Cooper (misc_124748)
----------------------------------------

Bourne shell (/bin/sh), as it stands, doesn't parse numbers properly, even though bash does:

[gcooper at optimus /devel/ncvs/src/bin/sh]$ sh -c 'exit -1'
exit: Illegal number: -1
[gcooper at optimus /devel/ncvs/src/bin/sh]$ sh -c 'exit +1'
exit: Illegal number: +1

These are valid numbers though, which are merely red herrings; the patch attached does fix this behavior though, according to the following gamut of tests:

[gcooper at optimus /devel/ncvs/src/bin/sh]$ cat number_test.sh
#!/bin/sh

for shell in sh $@; do
        for i in -1 1 +1; do
                echo "$shell -c \"exit $i\""
                $shell -c "exit $i"; echo $?
        done;
done
# End of test
[gcooper at optimus /devel/ncvs/src/bin/sh]$ ./number_test.sh bash ./sh
sh -c "exit -1"
exit: Illegal number: -1
2
sh -c "exit 1"
1
sh -c "exit +1"
exit: Illegal number: +1
2
bash -c "exit -1"
255
bash -c "exit 1"
1
bash -c "exit +1"
1
./sh -c "exit -1"
255
./sh -c "exit 1"
1
./sh -c "exit +1"
1

>How-To-Repeat:

(c) Garrett Cooper (misc_124748)
----------------------

/bin/sh -c "exit -1"
/bin/sh -c "exit +1"

>Fix:

(c) Garrett Cooper (misc_124748)
-----------------

Patch attached (also fixes histcmd.c and trap.c -- strange thing is that I can't seem to test that builtin cmd), and maintains proper compatibility with builtin jobs:

[gcooper at optimus /devel/ncvs/src/bin/sh]$ sh -c 'builtin histcmd'
histcmd: not found

Patch attached with submission follows:

Index: exec.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/exec.c,v
retrieving revision 1.31
diff -r1.31 exec.c
40a41
> #include <string.h>
361c362
<                       if (prefix("builtin", pathopt)) {
---
>                       if (strncmp(BUILTIN, pathopt, strlen(BUILTIN)) == 0) {
Index: histedit.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/histedit.c,v
retrieving revision 1.29
diff -r1.29 histedit.c
425,426d424
<       if (*s == '-')
<               s++;
Index: jobs.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/jobs.c,v
retrieving revision 1.72
diff -r1.72 jobs.c
534c534
<               return (jp);
---
>               return jp;
540c540,544
<                       jobno = number(name + 1);
---
>                       /*
>                        * Don't use number() here. This breaks existing
>                        * jobs(1) compatibility.
>                        */
>                       jobno = atoi(name + 1);
560c564
<                                       if (found)
---
>                                       if (found != NULL)
571,572c575,576
<                                && prefix(name + 1, jp->ps[0].cmd)) {
<                                       if (found)
---
>                                && strncmp(name+1, jp->ps[0].cmd, strlen(name+1))) {
>                                       if (found != NULL)
577,578c581,582
<                       if (found)
<                               return found;
---
>                       if (found != NULL)
>                               return (found);
581c585,586
<               pid = (pid_t)number(name);
---
>               /* no need to run is_number() again with number() */
>               pid = (pid_t)atoi(name);
Index: main.h
===================================================================
RCS file: /home/ncvs/src/bin/sh/main.h,v
retrieving revision 1.8
diff -r1.8 main.h
38a39,40
> #define BUILTIN "builtin"
>
Index: mystring.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/mystring.c,v
retrieving revision 1.13
diff -r1.13 mystring.c
56a57,59
> #if DEBUG
> #include <stdio.h>
> #endif
123a127,135
>       /* Is this the first index? */
>       int iter = 0;
>
> #if DEBUG
> #define PRINT_DEBUG fprintf(stderr, "%d: %c\n", iter, *p)
> #else
> #define PRINT_DEBUG
> #endif
>
125c137,154
<               if (! is_digit(*p))
---
>               /*
>                * Account for signs in front of numbers.
>                */
>
>               /*
>                * XXX: does POSIX bourne shell allow for '+' prefixed
>                * numbers?
>                */
>
>               /*
>                * The string defined by *p isn't a number, unless:
>                *      1. It's a digit.
>                *      2. The 0'th index is either a + or -.
>                */
>               if (!(is_digit(*p) ||
>                    (iter == 0 && (*p == '-' || *p == '+')))
>               ) {
>                       PRINT_DEBUG;
126a156,163
>               }
>
>               PRINT_DEBUG;
>
> #undef PRINT_DEBUG
>
>               iter++;
>

------------------------------


(c) Garrett Cooper (misc_124748) 

  



>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list