svn commit: r286941 - in head: lib/libc/gen tools/regression/lib/libc/gen

Jilles Tjoelker jilles at FreeBSD.org
Wed Aug 19 20:31:05 UTC 2015


Author: jilles
Date: Wed Aug 19 20:31:03 2015
New Revision: 286941
URL: https://svnweb.freebsd.org/changeset/base/286941

Log:
  wordexp(): Improve some error codes.
  
  Distinguish between WRDE_BADVAL and WRDE_SYNTAX based on when the error
  occurred (parsing or execution), not based on whether WRDE_UNDEF was passed.
  
  Also, return WRDE_NOSPACE for a few more unexpected results from sh.

Modified:
  head/lib/libc/gen/wordexp.3
  head/lib/libc/gen/wordexp.c
  head/tools/regression/lib/libc/gen/test-wordexp.c

Modified: head/lib/libc/gen/wordexp.3
==============================================================================
--- head/lib/libc/gen/wordexp.3	Wed Aug 19 20:10:58 2015	(r286940)
+++ head/lib/libc/gen/wordexp.3	Wed Aug 19 20:31:03 2015	(r286941)
@@ -131,9 +131,10 @@ argument contains one of the following u
 .Ql { ,
 .Ql } .
 .It Dv WRDE_BADVAL
-An attempt was made to expand an undefined shell variable and
+An error after successful parsing,
+such as an attempt to expand an undefined shell variable with
 .Dv WRDE_UNDEF
-is set in
+set in
 .Fa flags .
 .It Dv WRDE_CMDSUB
 An attempt was made to use command substitution and
@@ -141,7 +142,9 @@ An attempt was made to use command subst
 is set in
 .Fa flags .
 .It Dv WRDE_NOSPACE
-Not enough memory to store the result.
+Not enough memory to store the result or
+an error during
+.Xr fork 2 .
 .It Dv WRDE_SYNTAX
 Shell syntax error in
 .Fa words .

Modified: head/lib/libc/gen/wordexp.c
==============================================================================
--- head/lib/libc/gen/wordexp.c	Wed Aug 19 20:10:58 2015	(r286940)
+++ head/lib/libc/gen/wordexp.c	Wed Aug 19 20:31:03 2015	(r286941)
@@ -103,8 +103,7 @@ static int
 we_askshell(const char *words, wordexp_t *we, int flags)
 {
 	int pdes[2];			/* Pipe to child */
-	char bbuf[9];			/* Buffer for byte count */
-	char wbuf[9];			/* Buffer for word count */
+	char buf[18];			/* Buffer for byte and word count */
 	long nwords, nbytes;		/* Number of words, bytes from child */
 	long i;				/* Handy integer */
 	size_t sofs;			/* Offset into we->we_strings */
@@ -119,6 +118,7 @@ we_askshell(const char *words, wordexp_t
 	char **nwv;			/* Temporary for realloc() */
 	sigset_t newsigblock, oldsigblock;
 	const char *ifs;
+	char save;
 
 	serrno = errno;
 	ifs = getenv("IFS");
@@ -146,8 +146,9 @@ we_askshell(const char *words, wordexp_t
 		    _fcntl(pdes[1], F_SETFD, 0)) < 0)
 			_exit(1);
 		execl(_PATH_BSHELL, "sh", flags & WRDE_UNDEF ? "-u" : "+u",
-		    "-c", "IFS=$1;eval \"$2\";eval \"set -- $3\";IFS=;a=\"$*\";"
-		    "printf '%08x' \"$#\" \"${#a}\";printf '%s\\0' \"$@\"",
+		    "-c", "IFS=$1;eval \"$2\";eval \"echo;set -- $3\";"
+		    "IFS=;a=\"$*\";printf '%08x' \"$#\" \"${#a}\";"
+		    "printf '%s\\0' \"$@\"",
 		    "",
 		    ifs != NULL ? ifs : " \t\n",
 		    flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null", words,
@@ -157,20 +158,30 @@ we_askshell(const char *words, wordexp_t
 
 	/*
 	 * We are the parent; read the output of the shell wordexp function,
-	 * which is a 32-bit hexadecimal word count, a 32-bit hexadecimal
-	 * byte count (not including terminating null bytes), followed by
-	 * the expanded words separated by nulls.
+	 * which is a byte indicating that the words were parsed successfully,
+	 * a 32-bit hexadecimal word count, a 32-bit hexadecimal byte count
+	 * (not including terminating null bytes), followed by the expanded
+	 * words separated by nulls.
 	 */
 	_close(pdes[1]);
-	if (we_read_fully(pdes[0], wbuf, 8) != 8 ||
-			we_read_fully(pdes[0], bbuf, 8) != 8) {
-		error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
+	switch (we_read_fully(pdes[0], buf, 17)) {
+	case 1:
+		error = WRDE_BADVAL;
+		serrno = errno;
+		goto cleanup;
+	case 17:
+		break;
+	default:
+		error = WRDE_SYNTAX;
 		serrno = errno;
 		goto cleanup;
 	}
-	wbuf[8] = bbuf[8] = '\0';
-	nwords = strtol(wbuf, NULL, 16);
-	nbytes = strtol(bbuf, NULL, 16) + nwords;
+	save = buf[9];
+	buf[9] = '\0';
+	nwords = strtol(buf + 1, NULL, 16);
+	buf[9] = save;
+	buf[17] = '\0';
+	nbytes = strtol(buf + 9, NULL, 16) + nwords;
 
 	/*
 	 * Allocate or reallocate (when flags & WRDE_APPEND) the word vector
@@ -200,7 +211,7 @@ we_askshell(const char *words, wordexp_t
 	we->we_strings = nstrings;
 
 	if (we_read_fully(pdes[0], we->we_strings + sofs, nbytes) != nbytes) {
-		error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
+		error = WRDE_NOSPACE; /* abort for unknown reason */
 		serrno = errno;
 		goto cleanup;
 	}
@@ -217,7 +228,7 @@ cleanup:
 		return (error);
 	}
 	if (wpid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
-		return (flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX);
+		return (WRDE_NOSPACE); /* abort for unknown reason */
 
 	/*
 	 * Break the null-terminated expanded word strings out into

Modified: head/tools/regression/lib/libc/gen/test-wordexp.c
==============================================================================
--- head/tools/regression/lib/libc/gen/test-wordexp.c	Wed Aug 19 20:10:58 2015	(r286940)
+++ head/tools/regression/lib/libc/gen/test-wordexp.c	Wed Aug 19 20:31:03 2015	(r286941)
@@ -206,6 +206,15 @@ main(int argc, char *argv[])
 	assert(strcmp(we.we_wordv[0], "\\") == 0);
 	assert(we.we_wordv[1] == NULL);
 	wordfree(&we);
+	/* Two syntax errors that are not detected by the current we_check(). */
+	r = wordexp("${IFS:+'}", &we, 0);
+	assert(r == WRDE_SYNTAX);
+	r = wordexp("${IFS:+'}", &we, WRDE_UNDEF);
+	assert(r == WRDE_SYNTAX);
+	r = wordexp("$(case)", &we, 0);
+	assert(r == WRDE_SYNTAX);
+	r = wordexp("$(case)", &we, WRDE_UNDEF);
+	assert(r == WRDE_SYNTAX);
 
 	/* With a SIGCHLD handler that reaps all zombies. */
 	sa.sa_flags = 0;


More information about the svn-src-all mailing list