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 | |
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"
-rw-r--r-- | shell/hush.c | 13 | ||||
-rw-r--r-- | shell/hush_test/hush-leak/leak_argv1.right | 2 | ||||
-rw-r--r-- | shell/hush_test/hush-leak/leak_argv1.tests | 117 |
3 files changed, 129 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; |
diff --git a/shell/hush_test/hush-leak/leak_argv1.right b/shell/hush_test/hush-leak/leak_argv1.right new file mode 100644 index 000000000..7bccc1eef --- /dev/null +++ b/shell/hush_test/hush-leak/leak_argv1.right | |||
@@ -0,0 +1,2 @@ | |||
1 | Measuring memory leak... | ||
2 | vsz does not grow | ||
diff --git a/shell/hush_test/hush-leak/leak_argv1.tests b/shell/hush_test/hush-leak/leak_argv1.tests new file mode 100644 index 000000000..34991ce28 --- /dev/null +++ b/shell/hush_test/hush-leak/leak_argv1.tests | |||
@@ -0,0 +1,117 @@ | |||
1 | pid=$$ | ||
2 | |||
3 | # Warm up | ||
4 | beg=`ps -o pid,vsz | grep "^ *$pid "` | ||
5 | i=1 | ||
6 | while test $i != X; do | ||
7 | set -- a b c d e f g h i j k l m n o p q r s t u v w x y z | ||
8 | shift | ||
9 | shift 2 | ||
10 | shift 5 | ||
11 | shift 11 | ||
12 | set -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | ||
13 | shift 3 | ||
14 | shift 7 | ||
15 | i=1$i | ||
16 | if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi | ||
17 | if test $i = 1111111111111111111111111111111111111111111112; then i=3; fi | ||
18 | if test $i = 1111111111111111111111111111111111111111111113; then i=4; fi | ||
19 | if test $i = 1111111111111111111111111111111111111111111114; then i=5; fi | ||
20 | if test $i = 1111111111111111111111111111111111111111111115; then i=6; fi | ||
21 | if test $i = 1111111111111111111111111111111111111111111116; then i=7; fi | ||
22 | if test $i = 1111111111111111111111111111111111111111111117; then i=8; fi | ||
23 | if test $i = 1111111111111111111111111111111111111111111118; then i=9; fi | ||
24 | if test $i = 1111111111111111111111111111111111111111111119; then i=a; fi | ||
25 | if test $i = 111111111111111111111111111111111111111111111a; then i=b; fi | ||
26 | if test $i = 111111111111111111111111111111111111111111111b; then i=c; fi | ||
27 | if test $i = 111111111111111111111111111111111111111111111c; then i=d; fi | ||
28 | if test $i = 111111111111111111111111111111111111111111111d; then i=e; fi | ||
29 | if test $i = 111111111111111111111111111111111111111111111e; then i=f; fi | ||
30 | if test $i = 111111111111111111111111111111111111111111111f; then i=g; fi | ||
31 | if test $i = 111111111111111111111111111111111111111111111g; then i=h; fi | ||
32 | if test $i = 111111111111111111111111111111111111111111111h; then i=i; fi | ||
33 | if test $i = 111111111111111111111111111111111111111111111i; then i=j; fi | ||
34 | if test $i = 111111111111111111111111111111111111111111111j; then i=X; fi | ||
35 | done | ||
36 | end=`ps -o pid,vsz | grep "^ *$pid "` | ||
37 | |||
38 | # Warm up again (I do need it on my machine) | ||
39 | beg=`ps -o pid,vsz | grep "^ *$pid "` | ||
40 | i=1 | ||
41 | while test $i != X; do | ||
42 | set -- a b c d e f g h i j k l m n o p q r s t u v w x y z | ||
43 | shift | ||
44 | shift 2 | ||
45 | shift 5 | ||
46 | shift 11 | ||
47 | set -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | ||
48 | shift 3 | ||
49 | shift 7 | ||
50 | i=1$i | ||
51 | if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi | ||
52 | if test $i = 1111111111111111111111111111111111111111111112; then i=3; fi | ||
53 | if test $i = 1111111111111111111111111111111111111111111113; then i=4; fi | ||
54 | if test $i = 1111111111111111111111111111111111111111111114; then i=5; fi | ||
55 | if test $i = 1111111111111111111111111111111111111111111115; then i=6; fi | ||
56 | if test $i = 1111111111111111111111111111111111111111111116; then i=7; fi | ||
57 | if test $i = 1111111111111111111111111111111111111111111117; then i=8; fi | ||
58 | if test $i = 1111111111111111111111111111111111111111111118; then i=9; fi | ||
59 | if test $i = 1111111111111111111111111111111111111111111119; then i=a; fi | ||
60 | if test $i = 111111111111111111111111111111111111111111111a; then i=b; fi | ||
61 | if test $i = 111111111111111111111111111111111111111111111b; then i=c; fi | ||
62 | if test $i = 111111111111111111111111111111111111111111111c; then i=d; fi | ||
63 | if test $i = 111111111111111111111111111111111111111111111d; then i=e; fi | ||
64 | if test $i = 111111111111111111111111111111111111111111111e; then i=f; fi | ||
65 | if test $i = 111111111111111111111111111111111111111111111f; then i=g; fi | ||
66 | if test $i = 111111111111111111111111111111111111111111111g; then i=h; fi | ||
67 | if test $i = 111111111111111111111111111111111111111111111h; then i=i; fi | ||
68 | if test $i = 111111111111111111111111111111111111111111111i; then i=j; fi | ||
69 | if test $i = 111111111111111111111111111111111111111111111j; then i=X; fi | ||
70 | done | ||
71 | end=`ps -o pid,vsz | grep "^ *$pid "` | ||
72 | if test "$beg" != "$end"; then | ||
73 | true echo "vsz grows: $beg -> $end" | ||
74 | else | ||
75 | true echo "vsz does not grow" | ||
76 | fi | ||
77 | |||
78 | echo "Measuring memory leak..." | ||
79 | beg=`ps -o pid,vsz | grep "^ *$pid "` | ||
80 | i=1 | ||
81 | while test $i != X; do | ||
82 | set -- a b c d e f g h i j k l m n o p q r s t u v w x y z | ||
83 | shift | ||
84 | shift 2 | ||
85 | shift 5 | ||
86 | shift 11 | ||
87 | set -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | ||
88 | shift 3 | ||
89 | shift 7 | ||
90 | i=1$i | ||
91 | if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi | ||
92 | if test $i = 1111111111111111111111111111111111111111111112; then i=3; fi | ||
93 | if test $i = 1111111111111111111111111111111111111111111113; then i=4; fi | ||
94 | if test $i = 1111111111111111111111111111111111111111111114; then i=5; fi | ||
95 | if test $i = 1111111111111111111111111111111111111111111115; then i=6; fi | ||
96 | if test $i = 1111111111111111111111111111111111111111111116; then i=7; fi | ||
97 | if test $i = 1111111111111111111111111111111111111111111117; then i=8; fi | ||
98 | if test $i = 1111111111111111111111111111111111111111111118; then i=9; fi | ||
99 | if test $i = 1111111111111111111111111111111111111111111119; then i=a; fi | ||
100 | if test $i = 111111111111111111111111111111111111111111111a; then i=b; fi | ||
101 | if test $i = 111111111111111111111111111111111111111111111b; then i=c; fi | ||
102 | if test $i = 111111111111111111111111111111111111111111111c; then i=d; fi | ||
103 | if test $i = 111111111111111111111111111111111111111111111d; then i=e; fi | ||
104 | if test $i = 111111111111111111111111111111111111111111111e; then i=f; fi | ||
105 | if test $i = 111111111111111111111111111111111111111111111f; then i=g; fi | ||
106 | if test $i = 111111111111111111111111111111111111111111111g; then i=h; fi | ||
107 | if test $i = 111111111111111111111111111111111111111111111h; then i=i; fi | ||
108 | if test $i = 111111111111111111111111111111111111111111111i; then i=j; fi | ||
109 | if test $i = 111111111111111111111111111111111111111111111j; then i=X; fi | ||
110 | done | ||
111 | end=`ps -o pid,vsz | grep "^ *$pid "` | ||
112 | |||
113 | if test "$beg" != "$end"; then | ||
114 | echo "vsz grows: $beg -> $end" | ||
115 | else | ||
116 | echo "vsz does not grow" | ||
117 | fi | ||