diff options
| author | Eli Zaretskii | 2013-03-02 11:28:53 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-03-02 11:28:53 +0200 |
| commit | 18f2ac090d74eb0e91d5b3b8a6db01063264f254 (patch) | |
| tree | 0dd3fd6edf7382f5fcc58e660c85c0d7d9116b65 /src | |
| parent | c856b8d4679fe4b75f925c9e87eacf9456398090 (diff) | |
| download | emacs-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/ChangeLog | 7 | ||||
| -rw-r--r-- | src/textprop.c | 46 |
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 @@ | |||
| 1 | 2013-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 | |||
| 1 | 2013-02-28 Eli Zaretskii <eliz@gnu.org> | 8 | 2013-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 (;;) |