diff options
author | Ron Yorston <rmy@pobox.com> | 2021-04-25 11:55:01 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-28 11:29:33 +0200 |
commit | 852ffbee341ccbcdb6400ad5cb4688b410e236b5 (patch) | |
tree | 387aaa90dcebd1b66b4b79eae1a1b99905f09b74 | |
parent | dadd90974639c0b8cb0561eb946746ca2678b5fb (diff) | |
download | busybox-w32-852ffbee341ccbcdb6400ad5cb4688b410e236b5.tar.gz busybox-w32-852ffbee341ccbcdb6400ad5cb4688b410e236b5.tar.bz2 busybox-w32-852ffbee341ccbcdb6400ad5cb4688b410e236b5.zip |
vi: fix buffer overrun; code shrink
It was possible for get_input_line() to store its NUL terminator
one character beyond the end of its buffer.
Code shrink in colon():
- Certain colon commands can be matched exactly, as any shorter
string would be matched earlier, e.g. ':wq' versus ':write'.
- Command matching is now case sensitive so there's no need to
check for 'N' or 'Q' suffixes.
- Rewrite how commands and arguments are split.
function old new delta
colon 3848 3751 -97
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-97) Total: -97 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 53 |
1 files changed, 22 insertions, 31 deletions
diff --git a/editors/vi.c b/editors/vi.c index dd22eb45b..715961019 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -1191,7 +1191,7 @@ static char *get_input_line(const char *prompt) | |||
1191 | write1(prompt); // write out the :, /, or ? prompt | 1191 | write1(prompt); // write out the :, /, or ? prompt |
1192 | 1192 | ||
1193 | i = strlen(buf); | 1193 | i = strlen(buf); |
1194 | while (i < MAX_INPUT_LEN) { | 1194 | while (i < MAX_INPUT_LEN - 1) { |
1195 | c = get_one_char(); | 1195 | c = get_one_char(); |
1196 | if (c == '\n' || c == '\r' || c == 27) | 1196 | if (c == '\n' || c == '\r' || c == 27) |
1197 | break; // this is end of input | 1197 | break; // this is end of input |
@@ -2572,7 +2572,7 @@ static void colon(char *buf) | |||
2572 | if (cnt == 0) | 2572 | if (cnt == 0) |
2573 | return; | 2573 | return; |
2574 | if (strncmp(p, "quit", cnt) == 0 | 2574 | if (strncmp(p, "quit", cnt) == 0 |
2575 | || strncmp(p, "q!", cnt) == 0 | 2575 | || strcmp(p, "q!") == 0 |
2576 | ) { | 2576 | ) { |
2577 | if (modified_count && p[1] != '!') { | 2577 | if (modified_count && p[1] != '!') { |
2578 | status_line_bold("No write since last change (:%s! overrides)", p); | 2578 | status_line_bold("No write since last change (:%s! overrides)", p); |
@@ -2582,8 +2582,8 @@ static void colon(char *buf) | |||
2582 | return; | 2582 | return; |
2583 | } | 2583 | } |
2584 | if (strncmp(p, "write", cnt) == 0 | 2584 | if (strncmp(p, "write", cnt) == 0 |
2585 | || strncmp(p, "wq", cnt) == 0 | 2585 | || strcmp(p, "wq") == 0 |
2586 | || strncmp(p, "wn", cnt) == 0 | 2586 | || strcmp(p, "wn") == 0 |
2587 | || (p[0] == 'x' && !p[1]) | 2587 | || (p[0] == 'x' && !p[1]) |
2588 | ) { | 2588 | ) { |
2589 | if (modified_count != 0 || p[0] != 'x') { | 2589 | if (modified_count != 0 || p[0] != 'x') { |
@@ -2601,7 +2601,6 @@ static void colon(char *buf) | |||
2601 | ); | 2601 | ); |
2602 | if (p[0] == 'x' | 2602 | if (p[0] == 'x' |
2603 | || p[1] == 'q' || p[1] == 'n' | 2603 | || p[1] == 'q' || p[1] == 'n' |
2604 | || p[1] == 'Q' || p[1] == 'N' | ||
2605 | ) { | 2604 | ) { |
2606 | editing = 0; | 2605 | editing = 0; |
2607 | } | 2606 | } |
@@ -2621,10 +2620,9 @@ static void colon(char *buf) | |||
2621 | #else | 2620 | #else |
2622 | 2621 | ||
2623 | char c, *buf1, *q, *r; | 2622 | char c, *buf1, *q, *r; |
2624 | char *fn, cmd[MAX_INPUT_LEN], args[MAX_INPUT_LEN]; | 2623 | char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args; |
2625 | int i, l, li, b, e; | 2624 | int i, l, li, b, e; |
2626 | int useforce; | 2625 | int useforce; |
2627 | char *orig_buf; | ||
2628 | 2626 | ||
2629 | // :3154 // if (-e line 3154) goto it else stay put | 2627 | // :3154 // if (-e line 3154) goto it else stay put |
2630 | // :4,33w! foo // write a portion of buffer to file "foo" | 2628 | // :4,33w! foo // write a portion of buffer to file "foo" |
@@ -2652,35 +2650,29 @@ static void colon(char *buf) | |||
2652 | fn = current_filename; | 2650 | fn = current_filename; |
2653 | 2651 | ||
2654 | // look for optional address(es) :. :1 :1,9 :'q,'a :% | 2652 | // look for optional address(es) :. :1 :1,9 :'q,'a :% |
2655 | orig_buf = buf; | 2653 | buf1 = buf; |
2656 | buf = get_address(buf, &b, &e); | 2654 | buf = get_address(buf, &b, &e); |
2657 | if (buf == NULL) { | 2655 | if (buf == NULL) { |
2658 | status_line_bold("Bad address: %s", orig_buf); | 2656 | status_line_bold("Bad address: %s", buf1); |
2659 | goto ret; | 2657 | goto ret; |
2660 | } | 2658 | } |
2661 | 2659 | ||
2662 | # if ENABLE_FEATURE_VI_SEARCH || ENABLE_FEATURE_ALLOW_EXEC | ||
2663 | // remember orig command line | ||
2664 | orig_buf = buf; | ||
2665 | # endif | ||
2666 | |||
2667 | // get the COMMAND into cmd[] | 2660 | // get the COMMAND into cmd[] |
2661 | strcpy(cmd, buf); | ||
2668 | buf1 = cmd; | 2662 | buf1 = cmd; |
2669 | while (*buf != '\0') { | 2663 | while (!isspace(*buf1) && *buf1 != '\0') { |
2670 | if (isspace(*buf)) | 2664 | buf1++; |
2671 | break; | ||
2672 | *buf1++ = *buf++; | ||
2673 | } | 2665 | } |
2674 | *buf1 = '\0'; | 2666 | cmdend = buf1; |
2675 | // get any ARGuments | 2667 | // get any ARGuments |
2676 | while (isblank(*buf)) | 2668 | while (isblank(*buf1)) |
2677 | buf++; | 2669 | buf1++; |
2678 | strcpy(args, buf); | 2670 | args = buf1; |
2671 | *cmdend = '\0'; | ||
2679 | useforce = FALSE; | 2672 | useforce = FALSE; |
2680 | buf1 = last_char_is(cmd, '!'); | 2673 | if (cmdend > cmd && cmdend[-1] == '!') { |
2681 | if (buf1) { | ||
2682 | useforce = TRUE; | 2674 | useforce = TRUE; |
2683 | *buf1 = '\0'; // get rid of ! | 2675 | cmdend[-1] = '\0'; // get rid of ! |
2684 | } | 2676 | } |
2685 | // assume the command will want a range, certain commands | 2677 | // assume the command will want a range, certain commands |
2686 | // (read, substitute) need to adjust these assumptions | 2678 | // (read, substitute) need to adjust these assumptions |
@@ -2718,7 +2710,7 @@ static void colon(char *buf) | |||
2718 | // :!ls run the <cmd> | 2710 | // :!ls run the <cmd> |
2719 | go_bottom_and_clear_to_eol(); | 2711 | go_bottom_and_clear_to_eol(); |
2720 | cookmode(); | 2712 | cookmode(); |
2721 | retcode = system(orig_buf + 1); // run the cmd | 2713 | retcode = system(buf + 1); // run the cmd |
2722 | if (retcode) | 2714 | if (retcode) |
2723 | printf("\nshell returned %i\n\n", retcode); | 2715 | printf("\nshell returned %i\n\n", retcode); |
2724 | rawmode(); | 2716 | rawmode(); |
@@ -2969,8 +2961,8 @@ static void colon(char *buf) | |||
2969 | // F points to the "find" pattern | 2961 | // F points to the "find" pattern |
2970 | // R points to the "replace" pattern | 2962 | // R points to the "replace" pattern |
2971 | // replace the cmd line delimiters "/" with NULs | 2963 | // replace the cmd line delimiters "/" with NULs |
2972 | c = orig_buf[1]; // what is the delimiter | 2964 | c = buf[1]; // what is the delimiter |
2973 | F = orig_buf + 2; // start of "find" | 2965 | F = buf + 2; // start of "find" |
2974 | R = strchr(F, c); // middle delimiter | 2966 | R = strchr(F, c); // middle delimiter |
2975 | if (!R) | 2967 | if (!R) |
2976 | goto colon_s_fail; | 2968 | goto colon_s_fail; |
@@ -3039,8 +3031,8 @@ static void colon(char *buf) | |||
3039 | } else if (strncmp(cmd, "version", i) == 0) { // show software version | 3031 | } else if (strncmp(cmd, "version", i) == 0) { // show software version |
3040 | status_line(BB_VER); | 3032 | status_line(BB_VER); |
3041 | } else if (strncmp(cmd, "write", i) == 0 // write text to file | 3033 | } else if (strncmp(cmd, "write", i) == 0 // write text to file |
3042 | || strncmp(cmd, "wq", i) == 0 | 3034 | || strcmp(cmd, "wq") == 0 |
3043 | || strncmp(cmd, "wn", i) == 0 | 3035 | || strcmp(cmd, "wn") == 0 |
3044 | || (cmd[0] == 'x' && !cmd[1]) | 3036 | || (cmd[0] == 'x' && !cmd[1]) |
3045 | ) { | 3037 | ) { |
3046 | int size; | 3038 | int size; |
@@ -3096,7 +3088,6 @@ static void colon(char *buf) | |||
3096 | } | 3088 | } |
3097 | if (cmd[0] == 'x' | 3089 | if (cmd[0] == 'x' |
3098 | || cmd[1] == 'q' || cmd[1] == 'n' | 3090 | || cmd[1] == 'q' || cmd[1] == 'n' |
3099 | || cmd[1] == 'Q' || cmd[1] == 'N' | ||
3100 | ) { | 3091 | ) { |
3101 | editing = 0; | 3092 | editing = 0; |
3102 | } | 3093 | } |