diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-22 11:41:18 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-22 11:41:18 +0000 |
commit | e1300f6fc7a16e7c91f666192e66798eb40965be (patch) | |
tree | fbc3de6459418736adb1087a914a6770a194a70e /shell/hush.c | |
parent | 786ce17d6d602c471aab3cbd6ea00c854bfe9366 (diff) | |
download | busybox-w32-e1300f6fc7a16e7c91f666192e66798eb40965be.tar.gz busybox-w32-e1300f6fc7a16e7c91f666192e66798eb40965be.tar.bz2 busybox-w32-e1300f6fc7a16e7c91f666192e66798eb40965be.zip |
hush: fix segv at repeated "set -- a b c" + "shift"
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/shell/hush.c b/shell/hush.c index 2c4704a9c..9c0cd7c8e 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -471,8 +471,10 @@ struct globals { | |||
471 | smallint fake_mode; | 471 | smallint fake_mode; |
472 | /* these three support $?, $#, and $1 */ | 472 | /* these three support $?, $#, and $1 */ |
473 | smalluint last_return_code; | 473 | smalluint last_return_code; |
474 | /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */ | ||
474 | smalluint global_args_malloced; | 475 | smalluint global_args_malloced; |
475 | int global_argc; /* NB: $# + 1 */ | 476 | /* how many non-NULL argv's we have. NB: $# + 1 */ |
477 | int global_argc; | ||
476 | char **global_argv; | 478 | char **global_argv; |
477 | #if ENABLE_HUSH_LOOPS | 479 | #if ENABLE_HUSH_LOOPS |
478 | unsigned depth_break_continue; | 480 | unsigned depth_break_continue; |
@@ -4728,9 +4730,14 @@ static int builtin_shift(char **argv) | |||
4728 | n = atoi(argv[1]); | 4730 | n = atoi(argv[1]); |
4729 | } | 4731 | } |
4730 | if (n >= 0 && n < G.global_argc) { | 4732 | if (n >= 0 && n < G.global_argc) { |
4731 | G.global_argv[n] = G.global_argv[0]; | 4733 | if (G.global_args_malloced) { |
4734 | int m = 1; | ||
4735 | while (m <= n) | ||
4736 | free(G.global_argv[m++]); | ||
4737 | } | ||
4732 | G.global_argc -= n; | 4738 | G.global_argc -= n; |
4733 | G.global_argv += n; | 4739 | memmove(&G.global_argv[1], &G.global_argv[n+1], |
4740 | G.global_argc * sizeof(G.global_argv[0])); | ||
4734 | return EXIT_SUCCESS; | 4741 | return EXIT_SUCCESS; |
4735 | } | 4742 | } |
4736 | return EXIT_FAILURE; | 4743 | return EXIT_FAILURE; |