[bug] Vim-7.3a crashes with persistent undo and autocmd FileChangedRO

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[bug] Vim-7.3a crashes with persistent undo and autocmd FileChangedRO

Dominique Pellé
Hi

Vim-7.3a (2278:e41433ea71df) crashed while I was using undo.
It happened when doing undo on a file which was read-only
in perforce (not checked-out).  The Vim perforce plugin has
a FileChangedRO autocommand to automatically check-out
a file when attempting to change it. It causes a crash when
using persistent undo.

I found a simpler way to reproduce it without using the perforce
Plugin. The following script is enough to cause Vim to crash:

=========================================================
 #!/bin/sh

cd /tmp
rm -f foobar foobar.undo
vim -u NONE -N foobar \
  -c ':call feedkeys("aFOO\<Esc>:wundo! foobar.undo\<CR>:wq\<CR>")'
chmod a-w foobar

# Vim-7.3a (2278:e41433ea71df) will crash here.
vim -u NONE -N foobar \
  -c 'au FileChangedRO * :e!' \
  -c 'rundo foobar.undo' \
  -c 'undo'
=========================================================

Valgrind gives the following error (in the 2nd invocation of Vim):

==2892== Invalid read of size 4
==2892==    at 0x81C2FC1: u_freeentry (undo.c:3063)
==2892==    by 0x81C2F78: u_freeentries (undo.c:3044)
==2892==    by 0x81C2E55: u_freeheader (undo.c:2985)
==2892==    by 0x81C32E9: u_blockfree (undo.c:3173)
==2892==    by 0x8053C98: buf_freeall (buffer.c:579)
==2892==    by 0x8098C37: do_ecmd (ex_cmds.c:3573)
==2892==    by 0x80AF21E: do_exedit (ex_docmd.c:7626)
==2892==    by 0x80AEEDB: ex_edit (ex_docmd.c:7522)
==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
==2892==    by 0x80CE2CC: apply_autocmds_group (fileio.c:9334)
==2892==    by 0x80CDCDE: apply_autocmds (fileio.c:8943)
==2892==    by 0x810C467: change_warning (misc1.c:2995)
==2892==    by 0x810B78C: changed (misc1.c:2493)
==2892==    by 0x810BC8D: changed_common (misc1.c:2747)
==2892==    by 0x810BBA1: changed_lines (misc1.c:2692)
==2892==    by 0x81C2082: u_undoredo (undo.c:2487)
==2892==    by 0x81C127B: u_doit (undo.c:1962)
==2892==    by 0x81C112F: u_undo (undo.c:1907)
==2892==    by 0x80B0594: ex_undo (ex_docmd.c:8466)
==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
==2892==    by 0x80A4A4B: do_cmdline_cmd (ex_docmd.c:715)
==2892==    by 0x80EA19E: exe_commands (main.c:2755)
==2892==    by 0x80E7955: main (main.c:880)
==2892==  Address 0x4fc017c is 4 bytes inside a block of size 8 free'd
==2892==    at 0x4024B8A: free (vg_replace_malloc.c:366)
==2892==    by 0x8116ED6: vim_free (misc2.c:1702)
==2892==    by 0x81C1F9F: u_undoredo (undo.c:2473)
==2892==    by 0x81C127B: u_doit (undo.c:1962)
==2892==    by 0x81C112F: u_undo (undo.c:1907)
==2892==    by 0x80B0594: ex_undo (ex_docmd.c:8466)
==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
==2892==    by 0x80A4A4B: do_cmdline_cmd (ex_docmd.c:715)
==2892==    by 0x80EA19E: exe_commands (main.c:2755)
==2892==    by 0x80E7955: main (main.c:880)
(several more errors after that)

Source of src/undo.c:

2458   /* insert the lines in u_array between top and bot */
2459   if (newsize)
2460   {
2461       for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
2462       {
2463           /*
2464            * If the file is empty, there is an empty line 1 that we
2465            * should get rid of, by replacing it with the new line
2466            */
2467           if (empty_buffer && lnum == 0)
2468               ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
2469           else
2470               ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
2471           vim_free(uep->ue_array[i]);
2472       }
2473       vim_free((char_u *)uep->ue_array);  <--- MEMORY IS FREED
2474   }
2475
2476   /* adjust marks */
2477   if (oldsize != newsize)
2478   {
2479       mark_adjust(top + 1, top + oldsize, (long)MAXLNUM,
2480                                          (long)newsize - (long)oldsize);
2481       if (curbuf->b_op_start.lnum > top + oldsize)
2482           curbuf->b_op_start.lnum += newsize - oldsize;
2483       if (curbuf->b_op_end.lnum > top + oldsize)
2484           curbuf->b_op_end.lnum += newsize - oldsize;
2485   }
2486
2487   changed_lines(top + 1, 0, bot, newsize - oldsize); <--- USE FREE MEM

Not sure how to fix it yet,

-- Dominique

--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
Reply | Threaded
Open this post in threaded view
|

Re: [bug] Vim-7.3a crashes with persistent undo and autocmd FileChangedRO

Bram Moolenaar

Dominique Pelle wrote:

> Vim-7.3a (2278:e41433ea71df) crashed while I was using undo.
> It happened when doing undo on a file which was read-only
> in perforce (not checked-out).  The Vim perforce plugin has
> a FileChangedRO autocommand to automatically check-out
> a file when attempting to change it. It causes a crash when
> using persistent undo.
>
> I found a simpler way to reproduce it without using the perforce
> Plugin. The following script is enough to cause Vim to crash:
>
> =========================================================
>  #!/bin/sh
>
> cd /tmp
> rm -f foobar foobar.undo
> vim -u NONE -N foobar \
>   -c ':call feedkeys("aFOO\<Esc>:wundo! foobar.undo\<CR>:wq\<CR>")'
> chmod a-w foobar
>
> # Vim-7.3a (2278:e41433ea71df) will crash here.
> vim -u NONE -N foobar \
>   -c 'au FileChangedRO * :e!' \
>   -c 'rundo foobar.undo' \
>   -c 'undo'
> =========================================================
>
> Valgrind gives the following error (in the 2nd invocation of Vim):
>
> ==2892== Invalid read of size 4
> ==2892==    at 0x81C2FC1: u_freeentry (undo.c:3063)
> ==2892==    by 0x81C2F78: u_freeentries (undo.c:3044)
> ==2892==    by 0x81C2E55: u_freeheader (undo.c:2985)
> ==2892==    by 0x81C32E9: u_blockfree (undo.c:3173)
> ==2892==    by 0x8053C98: buf_freeall (buffer.c:579)
> ==2892==    by 0x8098C37: do_ecmd (ex_cmds.c:3573)
> ==2892==    by 0x80AF21E: do_exedit (ex_docmd.c:7626)
> ==2892==    by 0x80AEEDB: ex_edit (ex_docmd.c:7522)
> ==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
> ==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
> ==2892==    by 0x80CE2CC: apply_autocmds_group (fileio.c:9334)
> ==2892==    by 0x80CDCDE: apply_autocmds (fileio.c:8943)
> ==2892==    by 0x810C467: change_warning (misc1.c:2995)
> ==2892==    by 0x810B78C: changed (misc1.c:2493)
> ==2892==    by 0x810BC8D: changed_common (misc1.c:2747)
> ==2892==    by 0x810BBA1: changed_lines (misc1.c:2692)
> ==2892==    by 0x81C2082: u_undoredo (undo.c:2487)
> ==2892==    by 0x81C127B: u_doit (undo.c:1962)
> ==2892==    by 0x81C112F: u_undo (undo.c:1907)
> ==2892==    by 0x80B0594: ex_undo (ex_docmd.c:8466)
> ==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
> ==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
> ==2892==    by 0x80A4A4B: do_cmdline_cmd (ex_docmd.c:715)
> ==2892==    by 0x80EA19E: exe_commands (main.c:2755)
> ==2892==    by 0x80E7955: main (main.c:880)
> ==2892==  Address 0x4fc017c is 4 bytes inside a block of size 8 free'd
> ==2892==    at 0x4024B8A: free (vg_replace_malloc.c:366)
> ==2892==    by 0x8116ED6: vim_free (misc2.c:1702)
> ==2892==    by 0x81C1F9F: u_undoredo (undo.c:2473)
> ==2892==    by 0x81C127B: u_doit (undo.c:1962)
> ==2892==    by 0x81C112F: u_undo (undo.c:1907)
> ==2892==    by 0x80B0594: ex_undo (ex_docmd.c:8466)
> ==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
> ==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
> ==2892==    by 0x80A4A4B: do_cmdline_cmd (ex_docmd.c:715)
> ==2892==    by 0x80EA19E: exe_commands (main.c:2755)
> ==2892==    by 0x80E7955: main (main.c:880)
> (several more errors after that)
>
> Source of src/undo.c:
>
> 2458   /* insert the lines in u_array between top and bot */
> 2459   if (newsize)
> 2460   {
> 2461       for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
> 2462       {
> 2463           /*
> 2464            * If the file is empty, there is an empty line 1 that we
> 2465            * should get rid of, by replacing it with the new line
> 2466            */
> 2467           if (empty_buffer && lnum == 0)
> 2468               ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
> 2469           else
> 2470               ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
> 2471           vim_free(uep->ue_array[i]);
> 2472       }
> 2473       vim_free((char_u *)uep->ue_array);  <--- MEMORY IS FREED
> 2474   }
> 2475
> 2476   /* adjust marks */
> 2477   if (oldsize != newsize)
> 2478   {
> 2479       mark_adjust(top + 1, top + oldsize, (long)MAXLNUM,
> 2480                                          (long)newsize - (long)oldsize);
> 2481       if (curbuf->b_op_start.lnum > top + oldsize)
> 2482           curbuf->b_op_start.lnum += newsize - oldsize;
> 2483       if (curbuf->b_op_end.lnum > top + oldsize)
> 2484           curbuf->b_op_end.lnum += newsize - oldsize;
> 2485   }
> 2486
> 2487   changed_lines(top + 1, 0, bot, newsize - oldsize); <--- USE FREE MEM
>
> Not sure how to fix it yet,

Was this actually changed during the recent undo feature changes?
No, Vim 7.2 has the same code.  Thus it's actually an old problem.

--
Did you hear about the new 3 million dollar West Virginia State Lottery?
The winner gets 3 dollars a year for a million years.

 /// Bram Moolenaar -- [hidden email] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
Reply | Threaded
Open this post in threaded view
|

Re: [bug] Vim-7.3a crashes with persistent undo and autocmd FileChangedRO

Dominique Pellé
Bram Moolenaar wrote:

> Dominique Pelle wrote:
>
>> Vim-7.3a (2278:e41433ea71df) crashed while I was using undo.
>> It happened when doing undo on a file which was read-only
>> in perforce (not checked-out).  The Vim perforce plugin has
>> a FileChangedRO autocommand to automatically check-out
>> a file when attempting to change it. It causes a crash when
>> using persistent undo.
>>
>> I found a simpler way to reproduce it without using the perforce
>> Plugin. The following script is enough to cause Vim to crash:
>>
>> =========================================================
>>  #!/bin/sh
>>
>> cd /tmp
>> rm -f foobar foobar.undo
>> vim -u NONE -N foobar \
>>   -c ':call feedkeys("aFOO\<Esc>:wundo! foobar.undo\<CR>:wq\<CR>")'
>> chmod a-w foobar
>>
>> # Vim-7.3a (2278:e41433ea71df) will crash here.
>> vim -u NONE -N foobar \
>>   -c 'au FileChangedRO * :e!' \
>>   -c 'rundo foobar.undo' \
>>   -c 'undo'
>> =========================================================
>>
>> Valgrind gives the following error (in the 2nd invocation of Vim):
>>
>> ==2892== Invalid read of size 4
>> ==2892==    at 0x81C2FC1: u_freeentry (undo.c:3063)
>> ==2892==    by 0x81C2F78: u_freeentries (undo.c:3044)
>> ==2892==    by 0x81C2E55: u_freeheader (undo.c:2985)
>> ==2892==    by 0x81C32E9: u_blockfree (undo.c:3173)
>> ==2892==    by 0x8053C98: buf_freeall (buffer.c:579)
>> ==2892==    by 0x8098C37: do_ecmd (ex_cmds.c:3573)
>> ==2892==    by 0x80AF21E: do_exedit (ex_docmd.c:7626)
>> ==2892==    by 0x80AEEDB: ex_edit (ex_docmd.c:7522)
>> ==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
>> ==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
>> ==2892==    by 0x80CE2CC: apply_autocmds_group (fileio.c:9334)
>> ==2892==    by 0x80CDCDE: apply_autocmds (fileio.c:8943)
>> ==2892==    by 0x810C467: change_warning (misc1.c:2995)
>> ==2892==    by 0x810B78C: changed (misc1.c:2493)
>> ==2892==    by 0x810BC8D: changed_common (misc1.c:2747)
>> ==2892==    by 0x810BBA1: changed_lines (misc1.c:2692)
>> ==2892==    by 0x81C2082: u_undoredo (undo.c:2487)
>> ==2892==    by 0x81C127B: u_doit (undo.c:1962)
>> ==2892==    by 0x81C112F: u_undo (undo.c:1907)
>> ==2892==    by 0x80B0594: ex_undo (ex_docmd.c:8466)
>> ==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
>> ==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
>> ==2892==    by 0x80A4A4B: do_cmdline_cmd (ex_docmd.c:715)
>> ==2892==    by 0x80EA19E: exe_commands (main.c:2755)
>> ==2892==    by 0x80E7955: main (main.c:880)
>> ==2892==  Address 0x4fc017c is 4 bytes inside a block of size 8 free'd
>> ==2892==    at 0x4024B8A: free (vg_replace_malloc.c:366)
>> ==2892==    by 0x8116ED6: vim_free (misc2.c:1702)
>> ==2892==    by 0x81C1F9F: u_undoredo (undo.c:2473)
>> ==2892==    by 0x81C127B: u_doit (undo.c:1962)
>> ==2892==    by 0x81C112F: u_undo (undo.c:1907)
>> ==2892==    by 0x80B0594: ex_undo (ex_docmd.c:8466)
>> ==2892==    by 0x80A7AB8: do_one_cmd (ex_docmd.c:2640)
>> ==2892==    by 0x80A5391: do_cmdline (ex_docmd.c:1109)
>> ==2892==    by 0x80A4A4B: do_cmdline_cmd (ex_docmd.c:715)
>> ==2892==    by 0x80EA19E: exe_commands (main.c:2755)
>> ==2892==    by 0x80E7955: main (main.c:880)
>> (several more errors after that)
>>
>> Source of src/undo.c:
>>
>> 2458   /* insert the lines in u_array between top and bot */
>> 2459   if (newsize)
>> 2460   {
>> 2461       for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
>> 2462       {
>> 2463           /*
>> 2464            * If the file is empty, there is an empty line 1 that we
>> 2465            * should get rid of, by replacing it with the new line
>> 2466            */
>> 2467           if (empty_buffer && lnum == 0)
>> 2468               ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
>> 2469           else
>> 2470               ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
>> 2471           vim_free(uep->ue_array[i]);
>> 2472       }
>> 2473       vim_free((char_u *)uep->ue_array);  <--- MEMORY IS FREED
>> 2474   }
>> 2475
>> 2476   /* adjust marks */
>> 2477   if (oldsize != newsize)
>> 2478   {
>> 2479       mark_adjust(top + 1, top + oldsize, (long)MAXLNUM,
>> 2480                                          (long)newsize - (long)oldsize);
>> 2481       if (curbuf->b_op_start.lnum > top + oldsize)
>> 2482           curbuf->b_op_start.lnum += newsize - oldsize;
>> 2483       if (curbuf->b_op_end.lnum > top + oldsize)
>> 2484           curbuf->b_op_end.lnum += newsize - oldsize;
>> 2485   }
>> 2486
>> 2487   changed_lines(top + 1, 0, bot, newsize - oldsize); <--- USE FREE MEM
>>
>> Not sure how to fix it yet,
>
> Was this actually changed during the recent undo feature changes?
> No, Vim 7.2 has the same code.  Thus it's actually an old problem.


You're right.  I now see that it also happens with Vim-7.2.444.
The way to reproduce it has to be different though.
Following command crashes with both Vim-7.2.444 and
Vim-7.3a (2278:e41433ea71df):

$ rm foobar .foobar* ; ./vim -u NONE -N foobar \
   -c 'au FileChangedRO * e!' \
   -c 'norm iFOO' \
   -c 'set ro' \
   -c 'undo|redo'
Segmentation fault (core dumped)

-- Dominique

--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php