2 Subject: About patch 7.1.130
4 From: Bram Moolenaar <Bram@moolenaar.net>
6 Content-Type: text/plain; charset=ISO-8859-1
7 Content-Transfer-Encoding: 8bit
11 Problem: Crash with specific order of undo and redo. (A.Politz)
12 Solution: Clear and adjust pointers properly. Add u_check() for debugging.
13 Files: src/undo.c, src/structs.h
16 *** ../vim-7.1.129/src/undo.c Thu May 10 20:01:43 2007
17 --- src/undo.c Mon Oct 1 22:49:16 2007
24 + /* Uncomment the next line for including the u_check() function. This warns
25 + * for errors in the debug information. */
26 + /* #define U_DEBUG 1 */
27 + #define UH_MAGIC 0x18dade /* value for uh_magic when in use */
28 + #define UE_MAGIC 0xabc123 /* value for ue_magic when in use */
32 /* See below: use malloc()/free() for memory management. */
37 static int undo_undoes = FALSE;
41 + * Check the undo structures for being valid. Print a warning when something
44 + static int seen_b_u_curhead;
45 + static int seen_b_u_newhead;
46 + static int header_count;
49 + u_check_tree(u_header_T *uhp,
50 + u_header_T *exp_uh_next,
51 + u_header_T *exp_uh_alt_prev)
58 + if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1)
60 + EMSG("b_u_curhead found twice (looping?)");
63 + if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1)
65 + EMSG("b_u_newhead found twice (looping?)");
69 + if (uhp->uh_magic != UH_MAGIC)
70 + EMSG("uh_magic wrong (may be using freed memory)");
73 + /* Check pointers back are correct. */
74 + if (uhp->uh_next != exp_uh_next)
76 + EMSG("uh_next wrong");
77 + smsg((char_u *)"expected: 0x%x, actual: 0x%x",
78 + exp_uh_next, uhp->uh_next);
80 + if (uhp->uh_alt_prev != exp_uh_alt_prev)
82 + EMSG("uh_alt_prev wrong");
83 + smsg((char_u *)"expected: 0x%x, actual: 0x%x",
84 + exp_uh_alt_prev, uhp->uh_alt_prev);
87 + /* Check the undo tree at this header. */
88 + for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
90 + if (uep->ue_magic != UE_MAGIC)
92 + EMSG("ue_magic wrong (may be using freed memory)");
97 + /* Check the next alt tree. */
98 + u_check_tree(uhp->uh_alt_next, uhp->uh_next, uhp);
100 + /* Check the next header in this branch. */
101 + u_check_tree(uhp->uh_prev, uhp, NULL);
106 + u_check(int newhead_may_be_NULL)
108 + seen_b_u_newhead = 0;
109 + seen_b_u_curhead = 0;
112 + u_check_tree(curbuf->b_u_oldhead, NULL, NULL);
114 + if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL
115 + && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL))
116 + EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead);
117 + if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0)
118 + EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead);
119 + if (header_count != curbuf->b_u_numhead)
121 + EMSG("b_u_numhead invalid");
122 + smsg((char_u *)"expected: %ld, actual: %ld",
123 + (long)header_count, (long)curbuf->b_u_numhead);
129 * Save the current line for both the "u" and "U" command.
130 * Returns OK or FAIL.
140 #ifdef FEAT_NETBEANS_INTG
142 * Netbeans defines areas that cannot be modified. Bail out here when
146 uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T));
150 + uhp->uh_magic = UH_MAGIC;
158 u_header_T *uhfree = curbuf->b_u_oldhead;
160 ! /* If there is no branch only free one header. */
161 ! if (uhfree->uh_alt_next == NULL)
162 u_freeheader(curbuf, uhfree, &old_curhead);
167 u_header_T *uhfree = curbuf->b_u_oldhead;
169 ! if (uhfree == old_curhead)
170 ! /* Can't reconnect the branch, delete all of it. */
171 ! u_freebranch(curbuf, uhfree, &old_curhead);
172 ! else if (uhfree->uh_alt_next == NULL)
173 ! /* There is no branch, only free one header. */
174 u_freeheader(curbuf, uhfree, &old_curhead);
180 uhfree = uhfree->uh_alt_next;
181 u_freebranch(curbuf, uhfree, &old_curhead);
188 if (uhp == NULL) /* no undo at all */
192 uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
196 + uep->ue_magic = UE_MAGIC;
204 curbuf->b_u_synced = FALSE;
216 int empty_buffer; /* buffer became empty */
217 u_header_T *curhead = curbuf->b_u_curhead;
222 old_flags = curhead->uh_flags;
223 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
224 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
228 /* The timestamp can be the same for multiple changes, just use the one of
229 * the undone/redone change. */
230 curbuf->b_u_seq_time = curhead->uh_time;
242 ! * Free one header and its entry list and adjust the pointers.
245 u_freeheader(buf, uhp, uhpp)
250 ! * Free one header "uhp" and its entry list and adjust the pointers.
253 u_freeheader(buf, uhp, uhpp)
258 u_header_T **uhpp; /* if not NULL reset when freeing this header */
262 /* When there is an alternate redo list free that branch completely,
263 * because we can never go there. */
264 if (uhp->uh_alt_next != NULL)
267 if (uhp->uh_prev == NULL)
268 buf->b_u_newhead = uhp->uh_next;
270 ! uhp->uh_prev->uh_next = uhp->uh_next;
272 u_freeentries(buf, uhp, uhpp);
275 if (uhp->uh_prev == NULL)
276 buf->b_u_newhead = uhp->uh_next;
278 ! for (uhap = uhp->uh_prev; uhap != NULL; uhap = uhap->uh_alt_next)
279 ! uhap->uh_next = uhp->uh_next;
281 u_freeentries(buf, uhp, uhpp);
286 /* Check for pointers to the header that become invalid now. */
287 if (buf->b_u_curhead == uhp)
288 buf->b_u_curhead = NULL;
289 + if (buf->b_u_newhead == uhp)
290 + buf->b_u_newhead = NULL; /* freeing the newest entry */
291 if (uhpp != NULL && uhp == *uhpp)
297 u_freeentry(uep, uep->ue_size);
303 U_FREE_LINE((char_u *)uhp);
310 U_FREE_LINE(uep->ue_array[--n]);
311 U_FREE_LINE((char_u *)uep->ue_array);
315 U_FREE_LINE((char_u *)uep);
318 *** ../vim-7.1.129/src/structs.h Sun Aug 12 15:50:26 2007
319 --- src/structs.h Sat Sep 29 15:03:38 2007
323 linenr_T ue_lcount; /* linecount when u_save called */
324 char_u **ue_array; /* array of lines in undo block */
325 long ue_size; /* number of lines in ue_array */
327 + int ue_magic; /* magic number to check allocation */
335 visualinfo_T uh_visual; /* Visual areas before undo/after redo */
337 time_t uh_time; /* timestamp when the change was made */
339 + int uh_magic; /* magic number to check allocation */
343 /* values for uh_flags */
344 *** ../vim-7.1.129/src/version.c Mon Oct 1 20:33:45 2007
345 --- src/version.c Mon Oct 1 22:50:23 2007
349 { /* Add new patch number below this line */
355 FIRST SOLDIER: So they wouldn't be able to bring a coconut back anyway.
356 SECOND SOLDIER: Wait a minute! Suppose two swallows carried it together?
357 FIRST SOLDIER: No, they'd have to have it on a line.
358 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
360 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
361 /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
362 \\\ download, build and distribute -- http://www.A-A-P.org ///
363 \\\ help me help AIDS victims -- http://ICCF-Holland.org ///