bin/107674: sh(1): "type /NONEXISTENT" returns success

Martin Kammerhofer dada at pluto.tugraz.at
Mon Jan 8 03:00:32 PST 2007


>Number:         107674
>Category:       bin
>Synopsis:       sh(1): "type /NONEXISTENT" returns success
>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:   Mon Jan 08 11:00:29 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Martin Kammerhofer <dada at sbox.tugraz.at>
>Release:        FreeBSD 6.2-PRERELEASE i386
>Organization:
>Environment:
System: FreeBSD Martin.liebt.Susi 6.2-PRERELEASE FreeBSD 6.2-PRERELEASE #2: Tue Dec 5 13:15:11 CET 2006 toor at Martin.liebt.Susi:/usr/src/sys/i386/compile/P2B-S i386
>Description:

The type shell builtin indicates how each argument would be
interpreted if used as a command name. Shell scripts frequently
redirect the output to /dev/null and take a zero exit code as
confirmation that a command is available. (Similar to "test -x" which
only works with a single path name argument.)

Our sh(1) "forgets" to set the return code ($?) when testing a path
name argument, i.e. something containing the slash (/)
character. Therefore all such tests succeed unconditionally!

This e.g. breaks the hgmerge script installed with the devel/mercurial
port (when there are merge conflicts).

>How-To-Repeat:
$ /bin/sh -c "type /foo/bar && echo WE HAVE FOOBAR"
/foo/bar: No such file or directory
WE HAVE FOOBAR
$ /bin/sh -c "type /* && echo WE HAVE MANY COMMANDS IN /"

>Fix:
Index: exec.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/exec.c,v
retrieving revision 1.29
diff -u -r1.29 exec.c
--- exec.c	9 Apr 2006 12:21:20 -0000	1.29
+++ exec.c	6 Jan 2007 21:47:12 -0000
@@ -780,14 +780,16 @@
 						" a tracked alias for" : "",
 					    name);
 			} else {
-				if (access(argv[i], X_OK) == 0) {
+				if (eaccess(argv[i], X_OK) == 0) {
 					if (cmd == TYPECMD_SMALLV)
 						out1fmt("%s\n", argv[i]);
 					else
 						out1fmt(" is %s\n", argv[i]);
 				}
-				else
+				else {
 					out1fmt(": %s\n", strerror(errno));
+					error |= 127;
+				}
 			}
 			break;
 		}
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list