diff options
author | rbtnn <naru123456789@gmail.com> | 2021-08-20 20:54:25 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-08-20 20:54:25 +0200 |
commit | d895b1d918f7d56dd9dd564be4820082ba6492e9 (patch) | |
tree | fac233d7aa5b0b1428b32dbc16ff6b99b0ba1143 /src/vim9compile.c | |
parent | 5aec755b678cfd434b8ea2158d06992f33e1ff80 (diff) |
patch 8.2.3361: Vim9: crash with nested :whilev8.2.3361
Problem: Vim9: crash with nested :while.
Solution: Handle skipping better. (Naruhiko Nishino, closes #8778)
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r-- | src/vim9compile.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c index 5b47746e35..ccfb4ee16f 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4469,8 +4469,6 @@ compile_subscript( // dict member: dict[key] // string index: text[123] // blob index: blob[123] - // TODO: more arguments - // TODO: recognize list or dict at runtime if (generate_ppconst(cctx, ppconst) == FAIL) return FAIL; ppconst->pp_is_const = FALSE; @@ -8267,22 +8265,26 @@ compile_while(char_u *arg, cctx_T *cctx) // compile "expr" if (compile_expr0(&p, cctx) == FAIL) return NULL; + if (!ends_excmd2(arg, skipwhite(p))) { semsg(_(e_trailing_arg), p); return NULL; } - if (bool_on_stack(cctx) == FAIL) - return FAIL; + if (cctx->ctx_skip != SKIP_YES) + { + if (bool_on_stack(cctx) == FAIL) + return FAIL; - // CMDMOD_REV must come before the jump - generate_undo_cmdmods(cctx); + // CMDMOD_REV must come before the jump + generate_undo_cmdmods(cctx); - // "while_end" is set when ":endwhile" is found - if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label, + // "while_end" is set when ":endwhile" is found + if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label, JUMP_IF_FALSE, cctx) == FAIL) - return FAIL; + return FAIL; + } return p; } @@ -8304,20 +8306,23 @@ compile_endwhile(char_u *arg, cctx_T *cctx) return NULL; } cctx->ctx_scope = scope->se_outer; - unwind_locals(cctx, scope->se_local_count); + if (cctx->ctx_skip != SKIP_YES) + { + unwind_locals(cctx, scope->se_local_count); #ifdef FEAT_PROFILE - // count the endwhile before jumping - may_generate_prof_end(cctx, cctx->ctx_lnum); + // count the endwhile before jumping + may_generate_prof_end(cctx, cctx->ctx_lnum); #endif - // At end of ":for" scope jump back to the FOR instruction. - generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label); + // At end of ":for" scope jump back to the FOR instruction. + generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label); - // Fill in the "end" label in the WHILE statement so it can jump here. - // And in any jumps for ":break" - compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, + // Fill in the "end" label in the WHILE statement so it can jump here. + // And in any jumps for ":break" + compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, instr->ga_len, cctx); + } vim_free(scope); |