aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-03-02 11:28:53 +0200
committerEli Zaretskii2013-03-02 11:28:53 +0200
commit18f2ac090d74eb0e91d5b3b8a6db01063264f254 (patch)
tree0dd3fd6edf7382f5fcc58e660c85c0d7d9116b65 /src
parentc856b8d4679fe4b75f925c9e87eacf9456398090 (diff)
downloademacs-18f2ac090d74eb0e91d5b3b8a6db01063264f254.tar.gz
emacs-18f2ac090d74eb0e91d5b3b8a6db01063264f254.zip
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)
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog7
-rw-r--r--src/textprop.c46
2 files changed, 49 insertions, 4 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 1b8b3c56004..35cbab84096 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
12013-03-02 Eli Zaretskii <eliz@gnu.org>
2
3 * textprop.c (Fadd_text_properties, Fremove_text_properties): If
4 the interval tree changes as a side effect of calling
5 modify_region, re-do processing starting from the call to
6 validate_interval_range. (Bug#13743)
7
12013-02-28 Eli Zaretskii <eliz@gnu.org> 82013-02-28 Eli Zaretskii <eliz@gnu.org>
2 9
3 * w32.c (sys_open): Don't reset the flags for FD in fd_info[]. 10 * w32.c (sys_open): Don't reset the flags for FD in fd_info[].
diff --git a/src/textprop.c b/src/textprop.c
index 9499b53301f..34009131c09 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -1131,6 +1131,7 @@ Return t if any property value actually changed, nil otherwise. */)
1131 ptrdiff_t s, len; 1131 ptrdiff_t s, len;
1132 bool modified = 0; 1132 bool modified = 0;
1133 struct gcpro gcpro1; 1133 struct gcpro gcpro1;
1134 int first_time = 1;
1134 1135
1135 properties = validate_plist (properties); 1136 properties = validate_plist (properties);
1136 if (NILP (properties)) 1137 if (NILP (properties))
@@ -1139,6 +1140,7 @@ Return t if any property value actually changed, nil otherwise. */)
1139 if (NILP (object)) 1140 if (NILP (object))
1140 XSETBUFFER (object, current_buffer); 1141 XSETBUFFER (object, current_buffer);
1141 1142
1143 retry:
1142 i = validate_interval_range (object, &start, &end, hard); 1144 i = validate_interval_range (object, &start, &end, hard);
1143 if (!i) 1145 if (!i)
1144 return Qnil; 1146 return Qnil;
@@ -1174,8 +1176,25 @@ Return t if any property value actually changed, nil otherwise. */)
1174 copy_properties (unchanged, i); 1176 copy_properties (unchanged, i);
1175 } 1177 }
1176 1178
1177 if (BUFFERP (object)) 1179 if (BUFFERP (object) && first_time)
1178 modify_region (object, start, end); 1180 {
1181 ptrdiff_t prev_total_length = TOTAL_LENGTH (i);
1182 ptrdiff_t prev_pos = i->position;
1183
1184 modify_region (object, start, end);
1185 /* If someone called us recursively as a side effect of
1186 modify_region, and changed the intervals behind our back
1187 (could happen if lock_file, called by prepare_to_modify_buffer,
1188 triggers redisplay, and that calls add-text-properties again
1189 in the same buffer), we cannot continue with I, because its
1190 data changed. So we restart the interval analysis anew. */
1191 if (TOTAL_LENGTH (i) != prev_total_length
1192 || i->position != prev_pos)
1193 {
1194 first_time = 0;
1195 goto retry;
1196 }
1197 }
1179 1198
1180 /* We are at the beginning of interval I, with LEN chars to scan. */ 1199 /* We are at the beginning of interval I, with LEN chars to scan. */
1181 for (;;) 1200 for (;;)
@@ -1427,10 +1446,12 @@ Use `set-text-properties' if you want to remove all text properties. */)
1427 INTERVAL i, unchanged; 1446 INTERVAL i, unchanged;
1428 ptrdiff_t s, len; 1447 ptrdiff_t s, len;
1429 bool modified = 0; 1448 bool modified = 0;
1449 int first_time = 1;
1430 1450
1431 if (NILP (object)) 1451 if (NILP (object))
1432 XSETBUFFER (object, current_buffer); 1452 XSETBUFFER (object, current_buffer);
1433 1453
1454 retry:
1434 i = validate_interval_range (object, &start, &end, soft); 1455 i = validate_interval_range (object, &start, &end, soft);
1435 if (!i) 1456 if (!i)
1436 return Qnil; 1457 return Qnil;
@@ -1462,8 +1483,25 @@ Use `set-text-properties' if you want to remove all text properties. */)
1462 copy_properties (unchanged, i); 1483 copy_properties (unchanged, i);
1463 } 1484 }
1464 1485
1465 if (BUFFERP (object)) 1486 if (BUFFERP (object) && first_time)
1466 modify_region (object, start, end); 1487 {
1488 ptrdiff_t prev_total_length = TOTAL_LENGTH (i);
1489 ptrdiff_t prev_pos = i->position;
1490
1491 modify_region (object, start, end);
1492 /* If someone called us recursively as a side effect of
1493 modify_region, and changed the intervals behind our back
1494 (could happen if lock_file, called by prepare_to_modify_buffer,
1495 triggers redisplay, and that calls add-text-properties again
1496 in the same buffer), we cannot continue with I, because its
1497 data changed. So we restart the interval analysis anew. */
1498 if (TOTAL_LENGTH (i) != prev_total_length
1499 || i->position != prev_pos)
1500 {
1501 first_time = 0;
1502 goto retry;
1503 }
1504 }
1467 1505
1468 /* We are at the beginning of an interval, with len to scan */ 1506 /* We are at the beginning of an interval, with len to scan */
1469 for (;;) 1507 for (;;)