diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2014-09-15 17:06:10 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-09-15 17:06:10 +0200 |
commit | 05399fc53dc0b812727e44189882181ecaf3b6d6 (patch) | |
tree | efc93581856e68572359cfd3d6836a205352f0d1 | |
parent | 26a8b9f1967d910033c516462c101100e041a9b4 (diff) | |
download | busybox-w32-05399fc53dc0b812727e44189882181ecaf3b6d6.tar.gz busybox-w32-05399fc53dc0b812727e44189882181ecaf3b6d6.tar.bz2 busybox-w32-05399fc53dc0b812727e44189882181ecaf3b6d6.zip |
vi: fix incorrect memory access on brace matching. Closes 7256
While at it, fix brace matching to actually show the match
(missed fflush was causing cursor positioning to be buffered);
shorten brace matching code; remove unused macro indirection
in indicate_error().
Custom linker script 'busybox_ldscript' found, using it
function old new delta
indicate_error - 61 +61
mysleep 43 56 +13
char_insert 483 486 +3
find_pair 167 124 -43
Indicate_Error 61 - -61
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 2/1 up/down: 77/-104) Total: -27 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 79 |
1 files changed, 36 insertions, 43 deletions
diff --git a/editors/vi.c b/editors/vi.c index 24a9f60a8..70bdbab07 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -566,8 +566,7 @@ static void redraw(int); // force a full screen refresh | |||
566 | static char* format_line(char* /*, int*/); | 566 | static char* format_line(char* /*, int*/); |
567 | static void refresh(int); // update the terminal from screen[] | 567 | static void refresh(int); // update the terminal from screen[] |
568 | 568 | ||
569 | static void Indicate_Error(void); // use flash or beep to indicate error | 569 | static void indicate_error(void); // use flash or beep to indicate error |
570 | #define indicate_error(c) Indicate_Error() | ||
571 | static void Hit_Return(void); | 570 | static void Hit_Return(void); |
572 | 571 | ||
573 | #if ENABLE_FEATURE_VI_SEARCH | 572 | #if ENABLE_FEATURE_VI_SEARCH |
@@ -1840,11 +1839,11 @@ static char *bound_dot(char *p) // make sure text[0] <= P < "end" | |||
1840 | { | 1839 | { |
1841 | if (p >= end && end > text) { | 1840 | if (p >= end && end > text) { |
1842 | p = end - 1; | 1841 | p = end - 1; |
1843 | indicate_error('1'); | 1842 | indicate_error(); |
1844 | } | 1843 | } |
1845 | if (p < text) { | 1844 | if (p < text) { |
1846 | p = text; | 1845 | p = text; |
1847 | indicate_error('2'); | 1846 | indicate_error(); |
1848 | } | 1847 | } |
1849 | return p; | 1848 | return p; |
1850 | } | 1849 | } |
@@ -2023,16 +2022,9 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
2023 | p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char | 2022 | p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char |
2024 | } | 2023 | } |
2025 | } else { | 2024 | } else { |
2026 | #if ENABLE_FEATURE_VI_SETOPTS | ||
2027 | // insert a char into text[] | 2025 | // insert a char into text[] |
2028 | char *sp; // "save p" | ||
2029 | #endif | ||
2030 | |||
2031 | if (c == 13) | 2026 | if (c == 13) |
2032 | c = '\n'; // translate \r to \n | 2027 | c = '\n'; // translate \r to \n |
2033 | #if ENABLE_FEATURE_VI_SETOPTS | ||
2034 | sp = p; // remember addr of insert | ||
2035 | #endif | ||
2036 | #if ENABLE_FEATURE_VI_UNDO | 2028 | #if ENABLE_FEATURE_VI_UNDO |
2037 | # if ENABLE_FEATURE_VI_UNDO_QUEUE | 2029 | # if ENABLE_FEATURE_VI_UNDO_QUEUE |
2038 | if (c == '\n') | 2030 | if (c == '\n') |
@@ -2056,8 +2048,8 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
2056 | #endif /* ENABLE_FEATURE_VI_UNDO */ | 2048 | #endif /* ENABLE_FEATURE_VI_UNDO */ |
2057 | p += 1 + stupid_insert(p, c); // insert the char | 2049 | p += 1 + stupid_insert(p, c); // insert the char |
2058 | #if ENABLE_FEATURE_VI_SETOPTS | 2050 | #if ENABLE_FEATURE_VI_SETOPTS |
2059 | if (showmatch && strchr(")]}", *sp) != NULL) { | 2051 | if (showmatch && strchr(")]}", c) != NULL) { |
2060 | showmatching(sp); | 2052 | showmatching(p - 1); |
2061 | } | 2053 | } |
2062 | if (autoindent && c == '\n') { // auto indent the new line | 2054 | if (autoindent && c == '\n') { // auto indent the new line |
2063 | char *q; | 2055 | char *q; |
@@ -2217,34 +2209,32 @@ static char *skip_thing(char *p, int linecnt, int dir, int type) | |||
2217 | } | 2209 | } |
2218 | 2210 | ||
2219 | // find matching char of pair () [] {} | 2211 | // find matching char of pair () [] {} |
2212 | // will crash if c is not one of these | ||
2220 | static char *find_pair(char *p, const char c) | 2213 | static char *find_pair(char *p, const char c) |
2221 | { | 2214 | { |
2222 | char match, *q; | 2215 | const char *braces = "()[]{}"; |
2216 | char match; | ||
2223 | int dir, level; | 2217 | int dir, level; |
2224 | 2218 | ||
2225 | match = ')'; | 2219 | dir = strchr(braces, c) - braces; |
2220 | dir ^= 1; | ||
2221 | match = braces[dir]; | ||
2222 | dir = ((dir & 1) << 1) - 1; /* 1 for ([{, -1 for )\} */ | ||
2223 | |||
2224 | // look for match, count levels of pairs (( )) | ||
2226 | level = 1; | 2225 | level = 1; |
2227 | dir = 1; // assume forward | 2226 | for (;;) { |
2228 | switch (c) { | 2227 | p += dir; |
2229 | case '(': match = ')'; break; | 2228 | if (p < text || p >= end) |
2230 | case '[': match = ']'; break; | 2229 | return NULL; |
2231 | case '{': match = '}'; break; | 2230 | if (*p == c) |
2232 | case ')': match = '('; dir = -1; break; | ||
2233 | case ']': match = '['; dir = -1; break; | ||
2234 | case '}': match = '{'; dir = -1; break; | ||
2235 | } | ||
2236 | for (q = p + dir; text <= q && q < end; q += dir) { | ||
2237 | // look for match, count levels of pairs (( )) | ||
2238 | if (*q == c) | ||
2239 | level++; // increase pair levels | 2231 | level++; // increase pair levels |
2240 | if (*q == match) | 2232 | if (*p == match) { |
2241 | level--; // reduce pair level | 2233 | level--; // reduce pair level |
2242 | if (level == 0) | 2234 | if (level == 0) |
2243 | break; // found matching pair | 2235 | return p; // found matching pair |
2236 | } | ||
2244 | } | 2237 | } |
2245 | if (level != 0) | ||
2246 | q = NULL; // indicate no match | ||
2247 | return q; | ||
2248 | } | 2238 | } |
2249 | 2239 | ||
2250 | #if ENABLE_FEATURE_VI_SETOPTS | 2240 | #if ENABLE_FEATURE_VI_SETOPTS |
@@ -2256,7 +2246,7 @@ static void showmatching(char *p) | |||
2256 | // we found half of a pair | 2246 | // we found half of a pair |
2257 | q = find_pair(p, *p); // get loc of matching char | 2247 | q = find_pair(p, *p); // get loc of matching char |
2258 | if (q == NULL) { | 2248 | if (q == NULL) { |
2259 | indicate_error('3'); // no matching char | 2249 | indicate_error(); // no matching char |
2260 | } else { | 2250 | } else { |
2261 | // "q" now points to matching pair | 2251 | // "q" now points to matching pair |
2262 | save_dot = dot; // remember where we are | 2252 | save_dot = dot; // remember where we are |
@@ -2815,6 +2805,9 @@ static int mysleep(int hund) // sleep for 'hund' 1/100 seconds or stdin ready | |||
2815 | { | 2805 | { |
2816 | struct pollfd pfd[1]; | 2806 | struct pollfd pfd[1]; |
2817 | 2807 | ||
2808 | if (hund != 0) | ||
2809 | fflush_all(); | ||
2810 | |||
2818 | pfd[0].fd = STDIN_FILENO; | 2811 | pfd[0].fd = STDIN_FILENO; |
2819 | pfd[0].events = POLLIN; | 2812 | pfd[0].events = POLLIN; |
2820 | return safe_poll(pfd, 1, hund*10) > 0; | 2813 | return safe_poll(pfd, 1, hund*10) > 0; |
@@ -3059,7 +3052,7 @@ static void flash(int h) | |||
3059 | redraw(TRUE); | 3052 | redraw(TRUE); |
3060 | } | 3053 | } |
3061 | 3054 | ||
3062 | static void Indicate_Error(void) | 3055 | static void indicate_error(void) |
3063 | { | 3056 | { |
3064 | #if ENABLE_FEATURE_VI_CRASHME | 3057 | #if ENABLE_FEATURE_VI_CRASHME |
3065 | if (crashme > 0) | 3058 | if (crashme > 0) |
@@ -3602,7 +3595,7 @@ static void do_cmd(int c) | |||
3602 | break; | 3595 | break; |
3603 | case 27: // esc | 3596 | case 27: // esc |
3604 | if (cmd_mode == 0) | 3597 | if (cmd_mode == 0) |
3605 | indicate_error(c); | 3598 | indicate_error(); |
3606 | cmd_mode = 0; // stop insrting | 3599 | cmd_mode = 0; // stop insrting |
3607 | undo_queue_commit(); | 3600 | undo_queue_commit(); |
3608 | end_cmd_q(); | 3601 | end_cmd_q(); |
@@ -3621,7 +3614,7 @@ static void do_cmd(int c) | |||
3621 | if ((unsigned)c1 <= 25) { // a-z? | 3614 | if ((unsigned)c1 <= 25) { // a-z? |
3622 | YDreg = c1; | 3615 | YDreg = c1; |
3623 | } else { | 3616 | } else { |
3624 | indicate_error(c); | 3617 | indicate_error(); |
3625 | } | 3618 | } |
3626 | break; | 3619 | break; |
3627 | case '\'': // '- goto a specific mark | 3620 | case '\'': // '- goto a specific mark |
@@ -3639,7 +3632,7 @@ static void do_cmd(int c) | |||
3639 | dot_begin(); // go to B-o-l | 3632 | dot_begin(); // go to B-o-l |
3640 | dot_skip_over_ws(); | 3633 | dot_skip_over_ws(); |
3641 | } else { | 3634 | } else { |
3642 | indicate_error(c); | 3635 | indicate_error(); |
3643 | } | 3636 | } |
3644 | break; | 3637 | break; |
3645 | case 'm': // m- Mark a line | 3638 | case 'm': // m- Mark a line |
@@ -3652,7 +3645,7 @@ static void do_cmd(int c) | |||
3652 | // remember the line | 3645 | // remember the line |
3653 | mark[c1] = dot; | 3646 | mark[c1] = dot; |
3654 | } else { | 3647 | } else { |
3655 | indicate_error(c); | 3648 | indicate_error(); |
3656 | } | 3649 | } |
3657 | break; | 3650 | break; |
3658 | case 'P': // P- Put register before | 3651 | case 'P': // P- Put register before |
@@ -3713,7 +3706,7 @@ static void do_cmd(int c) | |||
3713 | // we found half of a pair | 3706 | // we found half of a pair |
3714 | p = find_pair(q, *q); | 3707 | p = find_pair(q, *q); |
3715 | if (p == NULL) { | 3708 | if (p == NULL) { |
3716 | indicate_error(c); | 3709 | indicate_error(); |
3717 | } else { | 3710 | } else { |
3718 | dot = p; | 3711 | dot = p; |
3719 | } | 3712 | } |
@@ -3721,7 +3714,7 @@ static void do_cmd(int c) | |||
3721 | } | 3714 | } |
3722 | } | 3715 | } |
3723 | if (*q == '\n') | 3716 | if (*q == '\n') |
3724 | indicate_error(c); | 3717 | indicate_error(); |
3725 | break; | 3718 | break; |
3726 | case 'f': // f- forward to a user specified char | 3719 | case 'f': // f- forward to a user specified char |
3727 | last_forward_char = get_one_char(); // get the search char | 3720 | last_forward_char = get_one_char(); // get the search char |
@@ -4054,7 +4047,7 @@ static void do_cmd(int c) | |||
4054 | // ZZ means to save file (if necessary), then exit | 4047 | // ZZ means to save file (if necessary), then exit |
4055 | c1 = get_one_char(); | 4048 | c1 = get_one_char(); |
4056 | if (c1 != 'Z') { | 4049 | if (c1 != 'Z') { |
4057 | indicate_error(c); | 4050 | indicate_error(); |
4058 | break; | 4051 | break; |
4059 | } | 4052 | } |
4060 | if (modified_count) { | 4053 | if (modified_count) { |
@@ -4138,7 +4131,7 @@ static void do_cmd(int c) | |||
4138 | // could not recognize object | 4131 | // could not recognize object |
4139 | c = c1 = 27; // error- | 4132 | c = c1 = 27; // error- |
4140 | ml = 0; | 4133 | ml = 0; |
4141 | indicate_error(c); | 4134 | indicate_error(); |
4142 | } | 4135 | } |
4143 | if (ml && whole) { | 4136 | if (ml && whole) { |
4144 | if (c == 'c') { | 4137 | if (c == 'c') { |