diff options
Diffstat (limited to 'package/busybox/busybox-1.13.3-hush.patch')
-rw-r--r-- | package/busybox/busybox-1.13.3-hush.patch | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/package/busybox/busybox-1.13.3-hush.patch b/package/busybox/busybox-1.13.3-hush.patch new file mode 100644 index 000000000..742f912fc --- /dev/null +++ b/package/busybox/busybox-1.13.3-hush.patch @@ -0,0 +1,179 @@ +diff -urpN busybox-1.13.3/shell/hush.c busybox-1.13.3-hush/shell/hush.c +--- busybox-1.13.3/shell/hush.c 2009-02-26 12:46:55.000000000 +0100 ++++ busybox-1.13.3-hush/shell/hush.c 2009-03-22 12:46:42.000000000 +0100 +@@ -458,8 +458,11 @@ struct globals { + smallint fake_mode; + /* these three support $?, $#, and $1 */ + smalluint last_return_code; +- char **global_argv; ++ /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */ ++ smalluint global_args_malloced; ++ /* how many non-NULL argv's we have. NB: $# + 1 */ + int global_argc; ++ char **global_argv; + #if ENABLE_HUSH_LOOPS + unsigned depth_break_continue; + unsigned depth_of_loop; +@@ -633,7 +636,7 @@ static char *unbackslash(char *src) + return dst; + } + +-static char **add_strings_to_strings(char **strings, char **add) ++static char **add_strings_to_strings(char **strings, char **add, int need_to_dup) + { + int i; + unsigned count1; +@@ -658,7 +661,7 @@ static char **add_strings_to_strings(cha + v[count1 + count2] = NULL; + i = count2; + while (--i >= 0) +- v[count1 + i] = add[i]; ++ v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]); + return v; + } + +@@ -667,7 +670,7 @@ static char **add_string_to_strings(char + char *v[2]; + v[0] = add; + v[1] = NULL; +- return add_strings_to_strings(strings, v); ++ return add_strings_to_strings(strings, v, /*dup:*/ 0); + } + + static void putenv_all(char **strings) +@@ -1213,8 +1216,13 @@ static int o_glob(o_string *o, int n) + * Otherwise, just finish current list[] and start new */ + static int o_save_ptr(o_string *o, int n) + { +- if (o->o_glob) +- return o_glob(o, n); /* o_save_ptr_helper is inside */ ++ if (o->o_glob) { /* if globbing is requested */ ++ /* If o->has_empty_slot, list[n] was already globbed ++ * (if it was requested back then when it was filled) ++ * so don't do that again! */ ++ if (!o->has_empty_slot) ++ return o_glob(o, n); /* o_save_ptr_helper is inside */ ++ } + return o_save_ptr_helper(o, n); + } + +@@ -4279,6 +4287,11 @@ int hush_main(int argc, char **argv) + switch (opt) { + case 'c': + G.global_argv = argv + optind; ++ if (!argv[optind]) { ++ /* -c 'script' (no params): prevent empty $0 */ ++ *--G.global_argv = argv[0]; ++ optind--; ++ } /* else -c 'script' PAR0 PAR1: $0 is PAR0 */ + G.global_argc = argc - optind; + opt = parse_and_run_string(optarg, 0 /* parse_flag */); + goto final_return; +@@ -4639,17 +4652,68 @@ static int builtin_read(char **argv) + return set_local_var(string, 0); + } + +-/* built-in 'set [VAR=value]' handler */ ++/* built-in 'set' handler ++ * SUSv3 says: ++ * set [-abCefmnuvx] [-h] [-o option] [argument...] ++ * set [+abCefmnuvx] [+h] [+o option] [argument...] ++ * set -- [argument...] ++ * set -o ++ * set +o ++ * Implementations shall support the options in both their hyphen and ++ * plus-sign forms. These options can also be specified as options to sh. ++ * Examples: ++ * Write out all variables and their values: set ++ * Set $1, $2, and $3 and set "$#" to 3: set c a b ++ * Turn on the -x and -v options: set -xv ++ * Unset all positional parameters: set -- ++ * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x" ++ * Set the positional parameters to the expansion of x, even if x expands ++ * with a leading '-' or '+': set -- $x ++ * ++ * So far, we only support "set -- [argument...]" by ignoring all options ++ * (also, "-o option" will be mishandled by taking "option" as parameter #1). ++ */ + static int builtin_set(char **argv) + { +- char *temp = argv[1]; + struct variable *e; ++ char **pp; ++ char *arg = *++argv; + +- if (temp == NULL) ++ if (arg == NULL) { + for (e = G.top_var; e; e = e->next) + puts(e->varstr); +- else +- set_local_var(xstrdup(temp), 0); ++ } else { ++ /* NB: G.global_argv[0] ($0) is never freed/changed */ ++ ++ if (G.global_args_malloced) { ++ pp = G.global_argv; ++ while (*++pp) ++ free(*pp); ++ G.global_argv[1] = NULL; ++ } else { ++ G.global_args_malloced = 1; ++ pp = xzalloc(sizeof(pp[0]) * 2); ++ pp[0] = G.global_argv[0]; /* retain $0 */ ++ G.global_argv = pp; ++ } ++ do { ++ if (arg[0] == '+') ++ continue; ++ if (arg[0] != '-') ++ break; ++ if (arg[1] == '-' && arg[2] == '\0') { ++ argv++; ++ break; ++ } ++ } while ((arg = *++argv) != NULL); ++ /* Now argv[0] is 1st argument */ ++ ++ /* This realloc's G.global_argv */ ++ G.global_argv = pp = add_strings_to_strings(G.global_argv, argv, /*dup:*/ 1); ++ G.global_argc = 1; ++ while (*++pp) ++ G.global_argc++; ++ } + + return EXIT_SUCCESS; + } +@@ -4661,9 +4725,14 @@ static int builtin_shift(char **argv) + n = atoi(argv[1]); + } + if (n >= 0 && n < G.global_argc) { +- G.global_argv[n] = G.global_argv[0]; ++ if (G.global_args_malloced) { ++ int m = 1; ++ while (m <= n) ++ free(G.global_argv[m++]); ++ } + G.global_argc -= n; +- G.global_argv += n; ++ memmove(&G.global_argv[1], &G.global_argv[n+1], ++ G.global_argc * sizeof(G.global_argv[0])); + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +diff -urpN busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.right busybox-1.13.3-hush/shell/hush_test/hush-parsing/starquoted2.right +--- busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.right 2009-02-26 12:46:52.000000000 +0100 ++++ busybox-1.13.3-hush/shell/hush_test/hush-parsing/starquoted2.right 2009-03-22 12:46:20.000000000 +0100 +@@ -1,2 +1,3 @@ + Should be printed + Should be printed ++Empty: +diff -urpN busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.tests busybox-1.13.3-hush/shell/hush_test/hush-parsing/starquoted2.tests +--- busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.tests 2009-02-26 12:46:52.000000000 +0100 ++++ busybox-1.13.3-hush/shell/hush_test/hush-parsing/starquoted2.tests 2009-03-22 12:46:20.000000000 +0100 +@@ -12,3 +12,6 @@ for a in "$@"""; do echo Should not be p + for a in """$@"; do echo Should not be printed; done + for a in """$@"''"$@"''; do echo Should not be printed; done + for a in ""; do echo Should be printed; done ++ ++# Bug 207: "$@" expands to nothing, and we erroneously glob "%s\\n" twice: ++printf "Empty:%s\\n" "$@" |