diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-27 12:14:39 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-27 12:14:39 +0200 |
| commit | 186cf4976768029113cf8438734a65bf2c489c5c (patch) | |
| tree | 0b2c2a4acad5472d65d87d7274cf91da2152d6b4 /shell | |
| parent | 7c5f18a3bab721cdfa515220ad8d481643aaae23 (diff) | |
| download | busybox-w32-186cf4976768029113cf8438734a65bf2c489c5c.tar.gz busybox-w32-186cf4976768029113cf8438734a65bf2c489c5c.tar.bz2 busybox-w32-186cf4976768029113cf8438734a65bf2c489c5c.zip | |
hush: in some cases, expand_on_ifs() relied of uninitialized memory
The n > 0 check to prevent access to the last byte of non-existing argv[-1]
wasn't enough. Switched to making sure there are initialized (zero) bytes there.
A predictable testcase is rather hard to construct, unfortunately,
contents of memory depends on allocator behavior and whatnot.
function old new delta
o_save_ptr_helper 119 137 +18
expand_on_ifs 345 339 -6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 18/-6) Total: 12 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/shell/hush.c b/shell/hush.c index 02fb1b5ef..1ac2db381 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -3069,6 +3069,13 @@ static int o_save_ptr_helper(o_string *o, int n) | |||
| 3069 | o->data = xrealloc(o->data, o->maxlen + 1); | 3069 | o->data = xrealloc(o->data, o->maxlen + 1); |
| 3070 | list = (char**)o->data; | 3070 | list = (char**)o->data; |
| 3071 | memmove(list + n + 0x10, list + n, string_len); | 3071 | memmove(list + n + 0x10, list + n, string_len); |
| 3072 | /* | ||
| 3073 | * expand_on_ifs() has a "previous argv[] ends in IFS?" | ||
| 3074 | * check. (grep for -prev-ifs-check-). | ||
| 3075 | * Ensure that argv[-1][last] is not garbage | ||
| 3076 | * but zero bytes, to save index check there. | ||
| 3077 | */ | ||
| 3078 | list[n + 0x10 - 1] = 0; | ||
| 3072 | o->length += 0x10 * sizeof(list[0]); | 3079 | o->length += 0x10 * sizeof(list[0]); |
| 3073 | } else { | 3080 | } else { |
| 3074 | debug_printf_list("list[%d]=%d string_start=%d\n", | 3081 | debug_printf_list("list[%d]=%d string_start=%d\n", |
| @@ -5797,12 +5804,16 @@ static int expand_on_ifs(o_string *output, int n, const char *str) | |||
| 5797 | /* Start new word... but not always! */ | 5804 | /* Start new word... but not always! */ |
| 5798 | /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ | 5805 | /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ |
| 5799 | if (output->has_quoted_part | 5806 | if (output->has_quoted_part |
| 5800 | /* Case "v=' a'; echo $v": | 5807 | /* |
| 5808 | * Case "v=' a'; echo $v": | ||
| 5801 | * here nothing precedes the space in $v expansion, | 5809 | * here nothing precedes the space in $v expansion, |
| 5802 | * therefore we should not finish the word | 5810 | * therefore we should not finish the word |
| 5803 | * (IOW: if there *is* word to finalize, only then do it): | 5811 | * (IOW: if there *is* word to finalize, only then do it): |
| 5812 | * It's okay if this accesses the byte before first argv[]: | ||
| 5813 | * past call to o_save_ptr() cleared it to zero byte | ||
| 5814 | * (grep for -prev-ifs-check-). | ||
| 5804 | */ | 5815 | */ |
| 5805 | || (n > 0 && output->data[output->length - 1]) | 5816 | || output->data[output->length - 1] |
| 5806 | ) { | 5817 | ) { |
| 5807 | new_word: | 5818 | new_word: |
| 5808 | o_addchr(output, '\0'); | 5819 | o_addchr(output, '\0'); |
