aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-09-09 12:35:49 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-09-09 12:35:49 +0200
commit12e154f0cf4dba7bc508356649f8d57ec1dbef37 (patch)
tree112e0f6b63c6b82f6b04a58893bd9e9e8aeb1139
parent289c47b04921a742e94bf07006eae3f0b97acc1f (diff)
downloadbusybox-w32-12e154f0cf4dba7bc508356649f8d57ec1dbef37.tar.gz
busybox-w32-12e154f0cf4dba7bc508356649f8d57ec1dbef37.tar.bz2
busybox-w32-12e154f0cf4dba7bc508356649f8d57ec1dbef37.zip
vi: prevent unlimited recursion in do_cmd(). Closes 4153
function old new delta do_cmd 4284 4194 -90 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/vi.c294
1 files changed, 139 insertions, 155 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 96a0c8df7..71d600834 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -3063,7 +3063,6 @@ static void refresh(int full_screen)
3063//----- Execute a Vi Command ----------------------------------- 3063//----- Execute a Vi Command -----------------------------------
3064static void do_cmd(int c) 3064static void do_cmd(int c)
3065{ 3065{
3066 const char *msg = msg; // for compiler
3067 char *p, *q, *save_dot; 3066 char *p, *q, *save_dot;
3068 char buf[12]; 3067 char buf[12];
3069 int dir; 3068 int dir;
@@ -3072,8 +3071,8 @@ static void do_cmd(int c)
3072 3071
3073// c1 = c; // quiet the compiler 3072// c1 = c; // quiet the compiler
3074// cnt = yf = 0; // quiet the compiler 3073// cnt = yf = 0; // quiet the compiler
3075// msg = p = q = save_dot = buf; // quiet the compiler 3074// p = q = save_dot = buf; // quiet the compiler
3076 memset(buf, '\0', 12); 3075 memset(buf, '\0', sizeof(buf));
3077 3076
3078 show_status_line(); 3077 show_status_line();
3079 3078
@@ -3189,19 +3188,18 @@ static void do_cmd(int c)
3189 case KEYCODE_LEFT: // cursor key Left 3188 case KEYCODE_LEFT: // cursor key Left
3190 case 8: // ctrl-H- move left (This may be ERASE char) 3189 case 8: // ctrl-H- move left (This may be ERASE char)
3191 case 0x7f: // DEL- move left (This may be ERASE char) 3190 case 0x7f: // DEL- move left (This may be ERASE char)
3192 if (--cmdcnt > 0) { 3191 do {
3193 do_cmd(c); 3192 dot_left();
3194 } 3193 } while (--cmdcnt > 0);
3195 dot_left();
3196 break; 3194 break;
3197 case 10: // Newline ^J 3195 case 10: // Newline ^J
3198 case 'j': // j- goto next line, same col 3196 case 'j': // j- goto next line, same col
3199 case KEYCODE_DOWN: // cursor key Down 3197 case KEYCODE_DOWN: // cursor key Down
3200 if (--cmdcnt > 0) { 3198 do {
3201 do_cmd(c); 3199 dot_next(); // go to next B-o-l
3202 } 3200 // try stay in same col
3203 dot_next(); // go to next B-o-l 3201 dot = move_to_col(dot, ccol + offset);
3204 dot = move_to_col(dot, ccol + offset); // try stay in same col 3202 } while (--cmdcnt > 0);
3205 break; 3203 break;
3206 case 12: // ctrl-L force redraw whole screen 3204 case 12: // ctrl-L force redraw whole screen
3207 case 18: // ctrl-R force redraw 3205 case 18: // ctrl-R force redraw
@@ -3214,11 +3212,10 @@ static void do_cmd(int c)
3214 break; 3212 break;
3215 case 13: // Carriage Return ^M 3213 case 13: // Carriage Return ^M
3216 case '+': // +- goto next line 3214 case '+': // +- goto next line
3217 if (--cmdcnt > 0) { 3215 do {
3218 do_cmd(c); 3216 dot_next();
3219 } 3217 dot_skip_over_ws();
3220 dot_next(); 3218 } while (--cmdcnt > 0);
3221 dot_skip_over_ws();
3222 break; 3219 break;
3223 case 21: // ctrl-U scroll up half screen 3220 case 21: // ctrl-U scroll up half screen
3224 dot_scroll((rows - 2) / 2, -1); 3221 dot_scroll((rows - 2) / 2, -1);
@@ -3236,10 +3233,9 @@ static void do_cmd(int c)
3236 case ' ': // move right 3233 case ' ': // move right
3237 case 'l': // move right 3234 case 'l': // move right
3238 case KEYCODE_RIGHT: // Cursor Key Right 3235 case KEYCODE_RIGHT: // Cursor Key Right
3239 if (--cmdcnt > 0) { 3236 do {
3240 do_cmd(c); 3237 dot_right();
3241 } 3238 } while (--cmdcnt > 0);
3242 dot_right();
3243 break; 3239 break;
3244#if ENABLE_FEATURE_VI_YANKMARK 3240#if ENABLE_FEATURE_VI_YANKMARK
3245 case '"': // "- name a register to use for Delete/Yank 3241 case '"': // "- name a register to use for Delete/Yank
@@ -3321,11 +3317,12 @@ static void do_cmd(int c)
3321#endif /* FEATURE_VI_YANKMARK */ 3317#endif /* FEATURE_VI_YANKMARK */
3322 case '$': // $- goto end of line 3318 case '$': // $- goto end of line
3323 case KEYCODE_END: // Cursor Key End 3319 case KEYCODE_END: // Cursor Key End
3324 if (--cmdcnt > 0) { 3320 for (;;) {
3321 dot = end_line(dot);
3322 if (--cmdcnt > 0)
3323 break;
3325 dot_next(); 3324 dot_next();
3326 do_cmd(c);
3327 } 3325 }
3328 dot = end_line(dot);
3329 break; 3326 break;
3330 case '%': // %- find matching char of pair () [] {} 3327 case '%': // %- find matching char of pair () [] {}
3331 for (q = dot; q < end && *q != '\n'; q++) { 3328 for (q = dot; q < end && *q != '\n'; q++) {
@@ -3350,38 +3347,35 @@ static void do_cmd(int c)
3350 // 3347 //
3351 //**** fall through to ... ';' 3348 //**** fall through to ... ';'
3352 case ';': // ;- look at rest of line for last forward char 3349 case ';': // ;- look at rest of line for last forward char
3353 if (--cmdcnt > 0) { 3350 do {
3354 do_cmd(';'); 3351 if (last_forward_char == 0)
3355 } 3352 break;
3356 if (last_forward_char == 0) 3353 q = dot + 1;
3357 break; 3354 while (q < end - 1 && *q != '\n' && *q != last_forward_char) {
3358 q = dot + 1; 3355 q++;
3359 while (q < end - 1 && *q != '\n' && *q != last_forward_char) { 3356 }
3360 q++; 3357 if (*q == last_forward_char)
3361 } 3358 dot = q;
3362 if (*q == last_forward_char) 3359 } while (--cmdcnt > 0);
3363 dot = q;
3364 break; 3360 break;
3365 case ',': // repeat latest 'f' in opposite direction 3361 case ',': // repeat latest 'f' in opposite direction
3366 if (--cmdcnt > 0) {
3367 do_cmd(',');
3368 }
3369 if (last_forward_char == 0) 3362 if (last_forward_char == 0)
3370 break; 3363 break;
3371 q = dot - 1; 3364 do {
3372 while (q >= text && *q != '\n' && *q != last_forward_char) { 3365 q = dot - 1;
3373 q--; 3366 while (q >= text && *q != '\n' && *q != last_forward_char) {
3374 } 3367 q--;
3375 if (q >= text && *q == last_forward_char) 3368 }
3376 dot = q; 3369 if (q >= text && *q == last_forward_char)
3370 dot = q;
3371 } while (--cmdcnt > 0);
3377 break; 3372 break;
3378 3373
3379 case '-': // -- goto prev line 3374 case '-': // -- goto prev line
3380 if (--cmdcnt > 0) { 3375 do {
3381 do_cmd(c); 3376 dot_prev();
3382 } 3377 dot_skip_over_ws();
3383 dot_prev(); 3378 } while (--cmdcnt > 0);
3384 dot_skip_over_ws();
3385 break; 3379 break;
3386#if ENABLE_FEATURE_VI_DOT_CMD 3380#if ENABLE_FEATURE_VI_DOT_CMD
3387 case '.': // .- repeat the last modifying command 3381 case '.': // .- repeat the last modifying command
@@ -3413,9 +3407,6 @@ static void do_cmd(int c)
3413 // user changed mind and erased the "/"- do nothing 3407 // user changed mind and erased the "/"- do nothing
3414 break; 3408 break;
3415 case 'N': // N- backward search for last pattern 3409 case 'N': // N- backward search for last pattern
3416 if (--cmdcnt > 0) {
3417 do_cmd(c);
3418 }
3419 dir = BACK; // assume BACKWARD search 3410 dir = BACK; // assume BACKWARD search
3420 p = dot - 1; 3411 p = dot - 1;
3421 if (last_search_pattern[0] == '?') { 3412 if (last_search_pattern[0] == '?') {
@@ -3427,41 +3418,41 @@ static void do_cmd(int c)
3427 case 'n': // n- repeat search for last pattern 3418 case 'n': // n- repeat search for last pattern
3428 // search rest of text[] starting at next char 3419 // search rest of text[] starting at next char
3429 // if search fails return orignal "p" not the "p+1" address 3420 // if search fails return orignal "p" not the "p+1" address
3430 if (--cmdcnt > 0) { 3421 do {
3431 do_cmd(c); 3422 const char *msg;
3432 }
3433 dc3: 3423 dc3:
3434 dir = FORWARD; // assume FORWARD search 3424 dir = FORWARD; // assume FORWARD search
3435 p = dot + 1; 3425 p = dot + 1;
3436 if (last_search_pattern[0] == '?') { 3426 if (last_search_pattern[0] == '?') {
3437 dir = BACK; 3427 dir = BACK;
3438 p = dot - 1; 3428 p = dot - 1;
3439 } 3429 }
3440 dc4: 3430 dc4:
3441 q = char_search(p, last_search_pattern + 1, dir, FULL); 3431 q = char_search(p, last_search_pattern + 1, dir, FULL);
3442 if (q != NULL) { 3432 if (q != NULL) {
3443 dot = q; // good search, update "dot" 3433 dot = q; // good search, update "dot"
3444 msg = ""; 3434 msg = NULL;
3445 goto dc2; 3435 goto dc2;
3446 } 3436 }
3447 // no pattern found between "dot" and "end"- continue at top 3437 // no pattern found between "dot" and "end"- continue at top
3448 p = text; 3438 p = text;
3449 if (dir == BACK) {
3450 p = end - 1;
3451 }
3452 q = char_search(p, last_search_pattern + 1, dir, FULL);
3453 if (q != NULL) { // found something
3454 dot = q; // found new pattern- goto it
3455 msg = "search hit BOTTOM, continuing at TOP";
3456 if (dir == BACK) { 3439 if (dir == BACK) {
3457 msg = "search hit TOP, continuing at BOTTOM"; 3440 p = end - 1;
3441 }
3442 q = char_search(p, last_search_pattern + 1, dir, FULL);
3443 if (q != NULL) { // found something
3444 dot = q; // found new pattern- goto it
3445 msg = "search hit BOTTOM, continuing at TOP";
3446 if (dir == BACK) {
3447 msg = "search hit TOP, continuing at BOTTOM";
3448 }
3449 } else {
3450 msg = "Pattern not found";
3458 } 3451 }
3459 } else {
3460 msg = "Pattern not found";
3461 }
3462 dc2: 3452 dc2:
3463 if (*msg) 3453 if (msg)
3464 status_line_bold("%s", msg); 3454 status_line_bold("%s", msg);
3455 } while (--cmdcnt > 0);
3465 break; 3456 break;
3466 case '{': // {- move backward paragraph 3457 case '{': // {- move backward paragraph
3467 q = char_search(dot, "\n\n", BACK, FULL); 3458 q = char_search(dot, "\n\n", BACK, FULL);
@@ -3580,18 +3571,17 @@ static void do_cmd(int c)
3580 case 'B': // B- back a blank-delimited Word 3571 case 'B': // B- back a blank-delimited Word
3581 case 'E': // E- end of a blank-delimited word 3572 case 'E': // E- end of a blank-delimited word
3582 case 'W': // W- forward a blank-delimited word 3573 case 'W': // W- forward a blank-delimited word
3583 if (--cmdcnt > 0) {
3584 do_cmd(c);
3585 }
3586 dir = FORWARD; 3574 dir = FORWARD;
3587 if (c == 'B') 3575 if (c == 'B')
3588 dir = BACK; 3576 dir = BACK;
3589 if (c == 'W' || isspace(dot[dir])) { 3577 do {
3590 dot = skip_thing(dot, 1, dir, S_TO_WS); 3578 if (c == 'W' || isspace(dot[dir])) {
3591 dot = skip_thing(dot, 2, dir, S_OVER_WS); 3579 dot = skip_thing(dot, 1, dir, S_TO_WS);
3592 } 3580 dot = skip_thing(dot, 2, dir, S_OVER_WS);
3593 if (c != 'W') 3581 }
3594 dot = skip_thing(dot, 1, dir, S_BEFORE_WS); 3582 if (c != 'W')
3583 dot = skip_thing(dot, 1, dir, S_BEFORE_WS);
3584 } while (--cmdcnt > 0);
3595 break; 3585 break;
3596 case 'C': // C- Change to e-o-l 3586 case 'C': // C- Change to e-o-l
3597 case 'D': // D- delete to e-o-l 3587 case 'D': // D- delete to e-o-l
@@ -3642,20 +3632,19 @@ static void do_cmd(int c)
3642 case 'i': // i- insert before current char 3632 case 'i': // i- insert before current char
3643 case KEYCODE_INSERT: // Cursor Key Insert 3633 case KEYCODE_INSERT: // Cursor Key Insert
3644 dc_i: 3634 dc_i:
3645 cmd_mode = 1; // start insrting 3635 cmd_mode = 1; // start inserting
3646 break; 3636 break;
3647 case 'J': // J- join current and next lines together 3637 case 'J': // J- join current and next lines together
3648 if (--cmdcnt > 1) { 3638 do {
3649 do_cmd(c); 3639 dot_end(); // move to NL
3650 } 3640 if (dot < end - 1) { // make sure not last char in text[]
3651 dot_end(); // move to NL 3641 *dot++ = ' '; // replace NL with space
3652 if (dot < end - 1) { // make sure not last char in text[] 3642 file_modified++;
3653 *dot++ = ' '; // replace NL with space 3643 while (isblank(*dot)) { // delete leading WS
3654 file_modified++; 3644 dot_delete();
3655 while (isblank(*dot)) { // delete leading WS 3645 }
3656 dot_delete();
3657 } 3646 }
3658 } 3647 } while (--cmdcnt > 0);
3659 end_cmd_q(); // stop adding to q 3648 end_cmd_q(); // stop adding to q
3660 break; 3649 break;
3661 case 'L': // L- goto bottom line on screen 3650 case 'L': // L- goto bottom line on screen
@@ -3699,20 +3688,19 @@ static void do_cmd(int c)
3699 case 'X': // X- delete char before dot 3688 case 'X': // X- delete char before dot
3700 case 'x': // x- delete the current char 3689 case 'x': // x- delete the current char
3701 case 's': // s- substitute the current char 3690 case 's': // s- substitute the current char
3702 if (--cmdcnt > 0) {
3703 do_cmd(c);
3704 }
3705 dir = 0; 3691 dir = 0;
3706 if (c == 'X') 3692 if (c == 'X')
3707 dir = -1; 3693 dir = -1;
3708 if (dot[dir] != '\n') { 3694 do {
3709 if (c == 'X') 3695 if (dot[dir] != '\n') {
3710 dot--; // delete prev char 3696 if (c == 'X')
3711 dot = yank_delete(dot, dot, 0, YANKDEL); // delete char 3697 dot--; // delete prev char
3712 } 3698 dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
3713 if (c == 's') 3699 }
3714 goto dc_i; // start insrting 3700 } while (--cmdcnt > 0);
3715 end_cmd_q(); // stop adding to q 3701 end_cmd_q(); // stop adding to q
3702 if (c == 's')
3703 goto dc_i; // start inserting
3716 break; 3704 break;
3717 case 'Z': // Z- if modified, {write}; exit 3705 case 'Z': // Z- if modified, {write}; exit
3718 // ZZ means to save file (if necessary), then exit 3706 // ZZ means to save file (if necessary), then exit
@@ -3743,23 +3731,22 @@ static void do_cmd(int c)
3743 break; 3731 break;
3744 case 'b': // b- back a word 3732 case 'b': // b- back a word
3745 case 'e': // e- end of word 3733 case 'e': // e- end of word
3746 if (--cmdcnt > 0) {
3747 do_cmd(c);
3748 }
3749 dir = FORWARD; 3734 dir = FORWARD;
3750 if (c == 'b') 3735 if (c == 'b')
3751 dir = BACK; 3736 dir = BACK;
3752 if ((dot + dir) < text || (dot + dir) > end - 1) 3737 do {
3753 break; 3738 if ((dot + dir) < text || (dot + dir) > end - 1)
3754 dot += dir; 3739 break;
3755 if (isspace(*dot)) { 3740 dot += dir;
3756 dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS); 3741 if (isspace(*dot)) {
3757 } 3742 dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS);
3758 if (isalnum(*dot) || *dot == '_') { 3743 }
3759 dot = skip_thing(dot, 1, dir, S_END_ALNUM); 3744 if (isalnum(*dot) || *dot == '_') {
3760 } else if (ispunct(*dot)) { 3745 dot = skip_thing(dot, 1, dir, S_END_ALNUM);
3761 dot = skip_thing(dot, 1, dir, S_END_PUNCT); 3746 } else if (ispunct(*dot)) {
3762 } 3747 dot = skip_thing(dot, 1, dir, S_END_PUNCT);
3748 }
3749 } while (--cmdcnt > 0);
3763 break; 3750 break;
3764 case 'c': // c- change something 3751 case 'c': // c- change something
3765 case 'd': // d- delete something 3752 case 'd': // d- delete something
@@ -3844,11 +3831,10 @@ static void do_cmd(int c)
3844 } 3831 }
3845 case 'k': // k- goto prev line, same col 3832 case 'k': // k- goto prev line, same col
3846 case KEYCODE_UP: // cursor key Up 3833 case KEYCODE_UP: // cursor key Up
3847 if (--cmdcnt > 0) { 3834 do {
3848 do_cmd(c); 3835 dot_prev();
3849 } 3836 dot = move_to_col(dot, ccol + offset); // try stay in same col
3850 dot_prev(); 3837 } while (--cmdcnt > 0);
3851 dot = move_to_col(dot, ccol + offset); // try stay in same col
3852 break; 3838 break;
3853 case 'r': // r- replace the current char with user input 3839 case 'r': // r- replace the current char with user input
3854 c1 = get_one_char(); // get the replacement char 3840 c1 = get_one_char(); // get the replacement char
@@ -3866,19 +3852,18 @@ static void do_cmd(int c)
3866 last_forward_char = 0; 3852 last_forward_char = 0;
3867 break; 3853 break;
3868 case 'w': // w- forward a word 3854 case 'w': // w- forward a word
3869 if (--cmdcnt > 0) { 3855 do {
3870 do_cmd(c); 3856 if (isalnum(*dot) || *dot == '_') { // we are on ALNUM
3871 } 3857 dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM);
3872 if (isalnum(*dot) || *dot == '_') { // we are on ALNUM 3858 } else if (ispunct(*dot)) { // we are on PUNCT
3873 dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM); 3859 dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT);
3874 } else if (ispunct(*dot)) { // we are on PUNCT 3860 }
3875 dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT); 3861 if (dot < end - 1)
3876 } 3862 dot++; // move over word
3877 if (dot < end - 1) 3863 if (isspace(*dot)) {
3878 dot++; // move over word 3864 dot = skip_thing(dot, 2, FORWARD, S_OVER_WS);
3879 if (isspace(*dot)) { 3865 }
3880 dot = skip_thing(dot, 2, FORWARD, S_OVER_WS); 3866 } while (--cmdcnt > 0);
3881 }
3882 break; 3867 break;
3883 case 'z': // z- 3868 case 'z': // z-
3884 c1 = get_one_char(); // get the replacement char 3869 c1 = get_one_char(); // get the replacement char
@@ -3894,17 +3879,16 @@ static void do_cmd(int c)
3894 dot = move_to_col(dot, cmdcnt - 1); // try to move to column 3879 dot = move_to_col(dot, cmdcnt - 1); // try to move to column
3895 break; 3880 break;
3896 case '~': // ~- flip the case of letters a-z -> A-Z 3881 case '~': // ~- flip the case of letters a-z -> A-Z
3897 if (--cmdcnt > 0) { 3882 do {
3898 do_cmd(c); 3883 if (islower(*dot)) {
3899 } 3884 *dot = toupper(*dot);
3900 if (islower(*dot)) { 3885 file_modified++;
3901 *dot = toupper(*dot); 3886 } else if (isupper(*dot)) {
3902 file_modified++; 3887 *dot = tolower(*dot);
3903 } else if (isupper(*dot)) { 3888 file_modified++;
3904 *dot = tolower(*dot); 3889 }
3905 file_modified++; 3890 dot_right();
3906 } 3891 } while (--cmdcnt > 0);
3907 dot_right();
3908 end_cmd_q(); // stop adding to q 3892 end_cmd_q(); // stop adding to q
3909 break; 3893 break;
3910 //----- The Cursor and Function Keys ----------------------------- 3894 //----- The Cursor and Function Keys -----------------------------