emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r111914: Protect against changes of i


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r111914: Protect against changes of interval tree when adding/removing text props.
Date: Sat, 02 Mar 2013 11:28:53 +0200
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 111914
fixes bug: http://debbugs.gnu.org/13743
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Sat 2013-03-02 11:28:53 +0200
message:
  Protect against changes of interval tree when adding/removing text props.
  
   src/textprop.c (Fadd_text_properties, Fremove_text_properties): If
   the interval tree changes as a side effect of calling
   modify_region, re-do processing starting from the call to
   validate_interval_range.  (Bug#13743)
modified:
  src/ChangeLog
  src/textprop.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-03-02 09:02:12 +0000
+++ b/src/ChangeLog     2013-03-02 09:28:53 +0000
@@ -1,3 +1,10 @@
+2013-03-02  Eli Zaretskii  <address@hidden>
+
+       * textprop.c (Fadd_text_properties, Fremove_text_properties): If
+       the interval tree changes as a side effect of calling
+       modify_region, re-do processing starting from the call to
+       validate_interval_range.  (Bug#13743)
+
 2013-02-28  Eli Zaretskii  <address@hidden>
 
        * w32.c (sys_open): Don't reset the flags for FD in fd_info[].

=== modified file 'src/textprop.c'
--- a/src/textprop.c    2013-02-26 03:09:08 +0000
+++ b/src/textprop.c    2013-03-02 09:28:53 +0000
@@ -1131,6 +1131,7 @@
   ptrdiff_t s, len;
   bool modified = 0;
   struct gcpro gcpro1;
+  int first_time = 1;
 
   properties = validate_plist (properties);
   if (NILP (properties))
@@ -1139,6 +1140,7 @@
   if (NILP (object))
     XSETBUFFER (object, current_buffer);
 
+ retry:
   i = validate_interval_range (object, &start, &end, hard);
   if (!i)
     return Qnil;
@@ -1174,8 +1176,25 @@
       copy_properties (unchanged, i);
     }
 
-  if (BUFFERP (object))
-    modify_region (object, start, end);
+  if (BUFFERP (object) && first_time)
+    {
+      ptrdiff_t prev_total_length = TOTAL_LENGTH (i);
+      ptrdiff_t prev_pos = i->position;
+
+      modify_region (object, start, end);
+      /* If someone called us recursively as a side effect of
+        modify_region, and changed the intervals behind our back
+        (could happen if lock_file, called by prepare_to_modify_buffer,
+        triggers redisplay, and that calls add-text-properties again
+        in the same buffer), we cannot continue with I, because its
+        data changed.  So we restart the interval analysis anew.  */
+      if (TOTAL_LENGTH (i) != prev_total_length
+         || i->position != prev_pos)
+       {
+         first_time = 0;
+         goto retry;
+       }
+    }
 
   /* We are at the beginning of interval I, with LEN chars to scan.  */
   for (;;)
@@ -1427,10 +1446,12 @@
   INTERVAL i, unchanged;
   ptrdiff_t s, len;
   bool modified = 0;
+  int first_time = 1;
 
   if (NILP (object))
     XSETBUFFER (object, current_buffer);
 
+ retry:
   i = validate_interval_range (object, &start, &end, soft);
   if (!i)
     return Qnil;
@@ -1462,8 +1483,25 @@
       copy_properties (unchanged, i);
     }
 
-  if (BUFFERP (object))
-    modify_region (object, start, end);
+  if (BUFFERP (object) && first_time)
+    {
+      ptrdiff_t prev_total_length = TOTAL_LENGTH (i);
+      ptrdiff_t prev_pos = i->position;
+
+      modify_region (object, start, end);
+      /* If someone called us recursively as a side effect of
+        modify_region, and changed the intervals behind our back
+        (could happen if lock_file, called by prepare_to_modify_buffer,
+        triggers redisplay, and that calls add-text-properties again
+        in the same buffer), we cannot continue with I, because its
+        data changed.  So we restart the interval analysis anew.  */
+      if (TOTAL_LENGTH (i) != prev_total_length
+         || i->position != prev_pos)
+       {
+         first_time = 0;
+         goto retry;
+       }
+    }
 
   /* We are at the beginning of an interval, with len to scan */
   for (;;)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]