To: vim-dev@vim.org Subject: Patch 7.2.445 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.2.445 Problem: Crash when using undo/redo and a FileChangedRO autocmd event that reloads the buffer. (Dominique Pelle) Solution: Do not allow autocommands while performing and undo or redo. Files: src/misc1.c, src/undo.c *** ../vim-7.2.444/src/misc1.c 2010-03-23 18:22:40.000000000 +0100 --- src/misc1.c 2010-07-07 18:18:52.000000000 +0200 *************** *** 2467,2476 **** } /* ! * changed() is called when something in the current buffer is changed. * * Most often called through changed_bytes() and changed_lines(), which also * mark the area of the display to be redrawn. */ void changed() --- 2467,2478 ---- } /* ! * Call this function when something in the current buffer is changed. * * Most often called through changed_bytes() and changed_lines(), which also * mark the area of the display to be redrawn. + * + * Careful: may trigger autocommands that reload the buffer. */ void changed() *************** *** 2536,2541 **** --- 2538,2544 ---- * - marks the windows on this buffer to be redisplayed * - marks the buffer changed by calling changed() * - invalidates cached values + * Careful: may trigger autocommands that reload the buffer. */ void changed_bytes(lnum, col) *************** *** 2649,2654 **** --- 2652,2658 ---- * below the changed lines (BEFORE the change). * When only inserting lines, "lnum" and "lnume" are equal. * Takes care of calling changed() and updating b_mod_*. + * Careful: may trigger autocommands that reload the buffer. */ void changed_lines(lnum, col, lnume, xtra) *************** *** 2716,2721 **** --- 2720,2730 ---- } } + /* + * Common code for when a change is was made. + * See changed_lines() for the arguments. + * Careful: may trigger autocommands that reload the buffer. + */ static void changed_common(lnum, col, lnume, xtra) linenr_T lnum; *************** *** 2966,2971 **** --- 2975,2981 ---- * Don't use emsg(), because it flushes the macro buffer. * If we have undone all changes b_changed will be FALSE, but "b_did_warn" * will be TRUE. + * Careful: may trigger autocommands that reload the buffer. */ void change_warning(col) *** ../vim-7.2.444/src/undo.c 2010-05-30 16:55:17.000000000 +0200 --- src/undo.c 2010-07-07 18:14:44.000000000 +0200 *************** *** 185,191 **** } } ! void u_check(int newhead_may_be_NULL) { seen_b_u_newhead = 0; --- 185,191 ---- } } ! static void u_check(int newhead_may_be_NULL) { seen_b_u_newhead = 0; *************** *** 320,325 **** --- 320,328 ---- return TRUE; } + /* + * Common code for various ways to save text before a change. + */ static int u_savecommon(top, bot, newbot) linenr_T top, bot; *************** *** 374,380 **** size = bot - top - 1; /* ! * if curbuf->b_u_synced == TRUE make a new header */ if (curbuf->b_u_synced) { --- 377,383 ---- size = bot - top - 1; /* ! * If curbuf->b_u_synced == TRUE make a new header. */ if (curbuf->b_u_synced) { *************** *** 709,714 **** --- 712,723 ---- u_oldcount = -1; while (count--) { + /* Do the change warning now, so that it triggers FileChangedRO when + * needed. This may cause the file to be reloaded, that must happen + * before we do anything, because it may change curbuf->b_u_curhead + * and more. */ + change_warning(0); + if (undo_undoes) { if (curbuf->b_u_curhead == NULL) /* first undo */ *************** *** 952,959 **** /* * First go up the tree as much as needed. */ ! for (;;) { uhp = curbuf->b_u_curhead; if (uhp == NULL) uhp = curbuf->b_u_newhead; --- 961,971 ---- /* * First go up the tree as much as needed. */ ! while (!got_int) { + /* Do the change warning now, for the same reason as above. */ + change_warning(0); + uhp = curbuf->b_u_curhead; if (uhp == NULL) uhp = curbuf->b_u_newhead; *************** *** 970,978 **** /* * And now go down the tree (redo), branching off where needed. */ ! uhp = curbuf->b_u_curhead; ! while (uhp != NULL) { /* Go back to the first branch with a mark. */ while (uhp->uh_alt_prev != NULL && uhp->uh_alt_prev->uh_walk == mark) --- 982,996 ---- /* * And now go down the tree (redo), branching off where needed. */ ! while (!got_int) { + /* Do the change warning now, for the same reason as above. */ + change_warning(0); + + uhp = curbuf->b_u_curhead; + if (uhp == NULL) + break; + /* Go back to the first branch with a mark. */ while (uhp->uh_alt_prev != NULL && uhp->uh_alt_prev->uh_walk == mark) *************** *** 1070,1075 **** --- 1088,1099 ---- int empty_buffer; /* buffer became empty */ u_header_T *curhead = curbuf->b_u_curhead; + #ifdef FEAT_AUTOCMD + /* Don't want autocommands using the undo structures here, they are + * invalid till the end. */ + block_autocmds(); + #endif + #ifdef U_DEBUG u_check(FALSE); #endif *************** *** 1099,1104 **** --- 1123,1131 ---- if (top > curbuf->b_ml.ml_line_count || top >= bot || bot > curbuf->b_ml.ml_line_count + 1) { + #ifdef FEAT_AUTOCMD + unblock_autocmds(); + #endif EMSG(_("E438: u_undo: line numbers wrong")); changed(); /* don't want UNCHANGED now */ return; *************** *** 1304,1309 **** --- 1331,1340 ---- /* The timestamp can be the same for multiple changes, just use the one of * the undone/redone change. */ curbuf->b_u_seq_time = curhead->uh_time; + + #ifdef FEAT_AUTOCMD + unblock_autocmds(); + #endif #ifdef U_DEBUG u_check(FALSE); #endif *** ../vim-7.2.444/src/version.c 2010-06-13 02:35:41.000000000 +0200 --- src/version.c 2010-07-07 18:18:27.000000000 +0200 *************** *** 683,684 **** --- 683,686 ---- { /* Add new patch number below this line */ + /**/ + 445, /**/ -- A KNIGHT rides into shot and hacks him to the ground. He rides off. We stay for a moment on the glade. A MIDDLE-AGED LADY in a C. & A. twin-set emerges from the trees and looks in horror at the body of her HUSBAND. MRS HISTORIAN: FRANK! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 ///