Commit 18f2ac09 authored by Eli Zaretskii's avatar Eli Zaretskii
Browse files

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)
parent c856b8d4
2013-03-02 Eli Zaretskii <eliz@gnu.org>
* 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 <eliz@gnu.org> 2013-02-28 Eli Zaretskii <eliz@gnu.org>
   
* w32.c (sys_open): Don't reset the flags for FD in fd_info[]. * w32.c (sys_open): Don't reset the flags for FD in fd_info[].
......
...@@ -1131,6 +1131,7 @@ Return t if any property value actually changed, nil otherwise. */) ...@@ -1131,6 +1131,7 @@ Return t if any property value actually changed, nil otherwise. */)
ptrdiff_t s, len; ptrdiff_t s, len;
bool modified = 0; bool modified = 0;
struct gcpro gcpro1; struct gcpro gcpro1;
int first_time = 1;
properties = validate_plist (properties); properties = validate_plist (properties);
if (NILP (properties)) if (NILP (properties))
...@@ -1139,6 +1140,7 @@ Return t if any property value actually changed, nil otherwise. */) ...@@ -1139,6 +1140,7 @@ Return t if any property value actually changed, nil otherwise. */)
if (NILP (object)) if (NILP (object))
XSETBUFFER (object, current_buffer); XSETBUFFER (object, current_buffer);
retry:
i = validate_interval_range (object, &start, &end, hard); i = validate_interval_range (object, &start, &end, hard);
if (!i) if (!i)
return Qnil; return Qnil;
...@@ -1174,8 +1176,25 @@ Return t if any property value actually changed, nil otherwise. */) ...@@ -1174,8 +1176,25 @@ Return t if any property value actually changed, nil otherwise. */)
copy_properties (unchanged, i); copy_properties (unchanged, i);
} }
if (BUFFERP (object)) if (BUFFERP (object) && first_time)
modify_region (object, start, end); {
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. */ /* We are at the beginning of interval I, with LEN chars to scan. */
for (;;) for (;;)
...@@ -1427,10 +1446,12 @@ Use `set-text-properties' if you want to remove all text properties. */) ...@@ -1427,10 +1446,12 @@ Use `set-text-properties' if you want to remove all text properties. */)
INTERVAL i, unchanged; INTERVAL i, unchanged;
ptrdiff_t s, len; ptrdiff_t s, len;
bool modified = 0; bool modified = 0;
int first_time = 1;
if (NILP (object)) if (NILP (object))
XSETBUFFER (object, current_buffer); XSETBUFFER (object, current_buffer);
retry:
i = validate_interval_range (object, &start, &end, soft); i = validate_interval_range (object, &start, &end, soft);
if (!i) if (!i)
return Qnil; return Qnil;
...@@ -1462,8 +1483,25 @@ Use `set-text-properties' if you want to remove all text properties. */) ...@@ -1462,8 +1483,25 @@ Use `set-text-properties' if you want to remove all text properties. */)
copy_properties (unchanged, i); copy_properties (unchanged, i);
} }
if (BUFFERP (object)) if (BUFFERP (object) && first_time)
modify_region (object, start, end); {
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 */ /* We are at the beginning of an interval, with len to scan */
for (;;) for (;;)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment