Mirror of the Vim source from https://github.com/vim/vim
リビジョン | 165a799b4129a922e3bbd97277a06538af75b616 (tree) |
---|---|
日時 | 2022-01-19 05:45:02 |
作者 | Bram Moolenaar <Bram@vim....> |
コミッター | Bram Moolenaar |
patch 8.2.4139: using freed memory in expression abbreviation
Commit: https://github.com/vim/vim/commit/94075b2b0e8e3b75334799d2c082497fbf85ffa1
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Jan 18 20:30:39 2022 +0000
@@ -226,7 +226,7 @@ | ||
226 | 226 | #endif |
227 | 227 | int simplified) |
228 | 228 | { |
229 | - mapblock_T *mp = ALLOC_ONE(mapblock_T); | |
229 | + mapblock_T *mp = ALLOC_CLEAR_ONE(mapblock_T); | |
230 | 230 | |
231 | 231 | if (mp == NULL) |
232 | 232 | return FAIL; |
@@ -1515,6 +1515,12 @@ | ||
1515 | 1515 | } |
1516 | 1516 | if (mp != NULL) |
1517 | 1517 | { |
1518 | + int noremap; | |
1519 | + int silent; | |
1520 | +#ifdef FEAT_EVAL | |
1521 | + int expr; | |
1522 | +#endif | |
1523 | + | |
1518 | 1524 | // Found a match: |
1519 | 1525 | // Insert the rest of the abbreviation in typebuf.tb_buf[]. |
1520 | 1526 | // This goes from end to start. |
@@ -1567,8 +1573,14 @@ | ||
1567 | 1573 | // insert the last typed char |
1568 | 1574 | (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent); |
1569 | 1575 | } |
1576 | + | |
1577 | + // copy values here, calling eval_map_expr() may make "mp" invalid! | |
1578 | + noremap = mp->m_noremap; | |
1579 | + silent = mp->m_silent; | |
1570 | 1580 | #ifdef FEAT_EVAL |
1571 | - if (mp->m_expr) | |
1581 | + expr = mp->m_expr; | |
1582 | + | |
1583 | + if (expr) | |
1572 | 1584 | s = eval_map_expr(mp, c); |
1573 | 1585 | else |
1574 | 1586 | #endif |
@@ -1576,11 +1588,11 @@ | ||
1576 | 1588 | if (s != NULL) |
1577 | 1589 | { |
1578 | 1590 | // insert the to string |
1579 | - (void)ins_typebuf(s, mp->m_noremap, 0, TRUE, mp->m_silent); | |
1591 | + (void)ins_typebuf(s, noremap, 0, TRUE, silent); | |
1580 | 1592 | // no abbrev. for these chars |
1581 | 1593 | typebuf.tb_no_abbr_cnt += (int)STRLEN(s) + j + 1; |
1582 | 1594 | #ifdef FEAT_EVAL |
1583 | - if (mp->m_expr) | |
1595 | + if (expr) | |
1584 | 1596 | vim_free(s); |
1585 | 1597 | #endif |
1586 | 1598 | } |
@@ -1590,7 +1602,7 @@ | ||
1590 | 1602 | if (has_mbyte) |
1591 | 1603 | len = clen; // Delete characters instead of bytes |
1592 | 1604 | while (len-- > 0) // delete the from string |
1593 | - (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent); | |
1605 | + (void)ins_typebuf(tb, 1, 0, TRUE, silent); | |
1594 | 1606 | return TRUE; |
1595 | 1607 | } |
1596 | 1608 | } |
@@ -1601,6 +1613,7 @@ | ||
1601 | 1613 | /* |
1602 | 1614 | * Evaluate the RHS of a mapping or abbreviations and take care of escaping |
1603 | 1615 | * special characters. |
1616 | + * Careful: after this "mp" will be invalid if the mapping was deleted. | |
1604 | 1617 | */ |
1605 | 1618 | char_u * |
1606 | 1619 | eval_map_expr( |
@@ -704,6 +704,11 @@ | ||
704 | 704 | mapclear |
705 | 705 | endfunc |
706 | 706 | |
707 | +func GetAbbrText() | |
708 | + unabbr hola | |
709 | + return 'hello' | |
710 | +endfunc | |
711 | + | |
707 | 712 | " Test for <expr> in abbreviation |
708 | 713 | func Test_expr_abbr() |
709 | 714 | new |
@@ -719,7 +724,14 @@ | ||
719 | 724 | call assert_equal('', getline(1)) |
720 | 725 | unabbr <expr> hte |
721 | 726 | |
722 | - close! | |
727 | + " evaluating the expression deletes the abbreviation | |
728 | + abbr <expr> hola GetAbbrText() | |
729 | + call assert_equal('GetAbbrText()', maparg('hola', 'i', '1')) | |
730 | + call feedkeys("ahola \<Esc>", 'xt') | |
731 | + call assert_equal('hello ', getline('.')) | |
732 | + call assert_equal('', maparg('hola', 'i', '1')) | |
733 | + | |
734 | + bwipe! | |
723 | 735 | endfunc |
724 | 736 | |
725 | 737 | " Test for storing mappings in different modes in a vimrc file |
@@ -751,6 +751,8 @@ | ||
751 | 751 | static int included_patches[] = |
752 | 752 | { /* Add new patch number below this line */ |
753 | 753 | /**/ |
754 | + 4139, | |
755 | +/**/ | |
754 | 756 | 4138, |
755 | 757 | /**/ |
756 | 758 | 4137, |