aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-02-25 18:13:42 +0200
committerEli Zaretskii2013-02-25 18:13:42 +0200
commit0248b0d70b891c952385daa787fb00c9bdd42935 (patch)
treeaafa490dd844b91e713981f8fcbd78b29a0a304f /src
parentb5071fc755c4f287c7befba1150d91a985762ebd (diff)
downloademacs-0248b0d70b891c952385daa787fb00c9bdd42935.tar.gz
emacs-0248b0d70b891c952385daa787fb00c9bdd42935.zip
Fix bug #13743 with crashes due to recursive add-text-properties.
src/textprop.c (Fadd_text_properties, Fremove_text_properties) (Fremove_list_of_text_properties): Skip all of the intervals in the region between START and END that already have resp. don't have the requested properties, not just the first one. Add assertions that the loop afterwards always modifies the properties.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog9
-rw-r--r--src/textprop.c125
2 files changed, 75 insertions, 59 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4f2fb4c1d53..dc9b97c3c03 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
12013-02-25 Eli Zaretskii <eliz@gnu.org>
2
3 * textprop.c (Fadd_text_properties, Fremove_text_properties)
4 (Fremove_list_of_text_properties): Skip all of the intervals in
5 the region between START and END that already have resp. don't
6 have the requested properties, not just the first one. Add
7 assertions that the loop afterwards always modifies the
8 properties. (Bug#13743)
9
12013-02-25 Stefan Monnier <monnier@iro.umontreal.ca> 102013-02-25 Stefan Monnier <monnier@iro.umontreal.ca>
2 11
3 * callint.c (Fcall_interactively): Use the right lexical environment 12 * callint.c (Fcall_interactively): Use the right lexical environment
diff --git a/src/textprop.c b/src/textprop.c
index c1f6e59bf2e..49fe427913c 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -1133,6 +1133,7 @@ Return t if any property value actually changed, nil otherwise. */)
1133 register ptrdiff_t s, len; 1133 register ptrdiff_t s, len;
1134 register int modified = 0; 1134 register int modified = 0;
1135 struct gcpro gcpro1; 1135 struct gcpro gcpro1;
1136 ptrdiff_t got;
1136 1137
1137 properties = validate_plist (properties); 1138 properties = validate_plist (properties);
1138 if (NILP (properties)) 1139 if (NILP (properties))
@@ -1152,26 +1153,25 @@ Return t if any property value actually changed, nil otherwise. */)
1152 and live buffers are always protected. */ 1153 and live buffers are always protected. */
1153 GCPRO1 (properties); 1154 GCPRO1 (properties);
1154 1155
1155 /* If we're not starting on an interval boundary, we have to 1156 /* If this interval already has the properties, we can skip it. */
1156 split this interval. */ 1157 if (interval_has_all_properties (properties, i))
1157 if (i->position != s)
1158 { 1158 {
1159 /* If this interval already has the properties, we can 1159 got = LENGTH (i) - (s - i->position);
1160 skip it. */ 1160 do {
1161 if (interval_has_all_properties (properties, i)) 1161 if (got >= len)
1162 { 1162 RETURN_UNGCPRO (Qnil);
1163 ptrdiff_t got = (LENGTH (i) - (s - i->position)); 1163 len -= got;
1164 if (got >= len) 1164 i = next_interval (i);
1165 RETURN_UNGCPRO (Qnil); 1165 got = LENGTH (i);
1166 len -= got; 1166 } while (interval_has_all_properties (properties, i));
1167 i = next_interval (i); 1167 }
1168 } 1168 else if (i->position != s)
1169 else 1169 {
1170 { 1170 /* If we're not starting on an interval boundary, we have to
1171 unchanged = i; 1171 split this interval. */
1172 i = split_interval_right (unchanged, s - unchanged->position); 1172 unchanged = i;
1173 copy_properties (unchanged, i); 1173 i = split_interval_right (unchanged, s - unchanged->position);
1174 } 1174 copy_properties (unchanged, i);
1175 } 1175 }
1176 1176
1177 if (BUFFERP (object)) 1177 if (BUFFERP (object))
@@ -1195,7 +1195,8 @@ Return t if any property value actually changed, nil otherwise. */)
1195 signal_after_change (XINT (start), XINT (end) - XINT (start), 1195 signal_after_change (XINT (start), XINT (end) - XINT (start),
1196 XINT (end) - XINT (start)); 1196 XINT (end) - XINT (start));
1197 1197
1198 return modified ? Qt : Qnil; 1198 eassert (modified);
1199 return Qt;
1199 } 1200 }
1200 1201
1201 if (LENGTH (i) == len) 1202 if (LENGTH (i) == len)
@@ -1426,6 +1427,7 @@ Use `set-text-properties' if you want to remove all text properties. */)
1426 register INTERVAL i, unchanged; 1427 register INTERVAL i, unchanged;
1427 register ptrdiff_t s, len; 1428 register ptrdiff_t s, len;
1428 register int modified = 0; 1429 register int modified = 0;
1430 ptrdiff_t got;
1429 1431
1430 if (NILP (object)) 1432 if (NILP (object))
1431 XSETBUFFER (object, current_buffer); 1433 XSETBUFFER (object, current_buffer);
@@ -1437,26 +1439,25 @@ Use `set-text-properties' if you want to remove all text properties. */)
1437 s = XINT (start); 1439 s = XINT (start);
1438 len = XINT (end) - s; 1440 len = XINT (end) - s;
1439 1441
1440 if (i->position != s) 1442 /* If there are no properties on this entire interval, return. */
1443 if (! interval_has_some_properties (properties, i))
1441 { 1444 {
1442 /* No properties on this first interval -- return if 1445 got = (LENGTH (i) - (s - i->position));
1443 it covers the entire region. */ 1446 do {
1444 if (! interval_has_some_properties (properties, i)) 1447 if (got >= len)
1445 { 1448 return Qnil;
1446 ptrdiff_t got = (LENGTH (i) - (s - i->position)); 1449 len -= got;
1447 if (got >= len) 1450 i = next_interval (i);
1448 return Qnil; 1451 got = LENGTH (i);
1449 len -= got; 1452 } while (! interval_has_some_properties (properties, i));
1450 i = next_interval (i); 1453 }
1451 } 1454 /* Split away the beginning of this interval; what we don't
1452 /* Split away the beginning of this interval; what we don't 1455 want to modify. */
1453 want to modify. */ 1456 else if (i->position != s)
1454 else 1457 {
1455 { 1458 unchanged = i;
1456 unchanged = i; 1459 i = split_interval_right (unchanged, s - unchanged->position);
1457 i = split_interval_right (unchanged, s - unchanged->position); 1460 copy_properties (unchanged, i);
1458 copy_properties (unchanged, i);
1459 }
1460 } 1461 }
1461 1462
1462 if (BUFFERP (object)) 1463 if (BUFFERP (object))
@@ -1470,7 +1471,13 @@ Use `set-text-properties' if you want to remove all text properties. */)
1470 if (LENGTH (i) >= len) 1471 if (LENGTH (i) >= len)
1471 { 1472 {
1472 if (! interval_has_some_properties (properties, i)) 1473 if (! interval_has_some_properties (properties, i))
1473 return modified ? Qt : Qnil; 1474 {
1475 eassert (modified);
1476 if (BUFFERP (object))
1477 signal_after_change (XINT (start), XINT (end) - XINT (start),
1478 XINT (end) - XINT (start));
1479 return Qt;
1480 }
1474 1481
1475 if (LENGTH (i) == len) 1482 if (LENGTH (i) == len)
1476 { 1483 {
@@ -1512,6 +1519,7 @@ Return t if any property was actually removed, nil otherwise. */)
1512 register ptrdiff_t s, len; 1519 register ptrdiff_t s, len;
1513 register int modified = 0; 1520 register int modified = 0;
1514 Lisp_Object properties; 1521 Lisp_Object properties;
1522 ptrdiff_t got;
1515 properties = list_of_properties; 1523 properties = list_of_properties;
1516 1524
1517 if (NILP (object)) 1525 if (NILP (object))
@@ -1524,26 +1532,25 @@ Return t if any property was actually removed, nil otherwise. */)
1524 s = XINT (start); 1532 s = XINT (start);
1525 len = XINT (end) - s; 1533 len = XINT (end) - s;
1526 1534
1527 if (i->position != s) 1535 /* If there are no properties on the interval, return. */
1536 if (! interval_has_some_properties_list (properties, i))
1528 { 1537 {
1529 /* No properties on this first interval -- return if 1538 got = (LENGTH (i) - (s - i->position));
1530 it covers the entire region. */ 1539 do {
1531 if (! interval_has_some_properties_list (properties, i)) 1540 if (got >= len)
1532 { 1541 return Qnil;
1533 ptrdiff_t got = (LENGTH (i) - (s - i->position)); 1542 len -= got;
1534 if (got >= len) 1543 i = next_interval (i);
1535 return Qnil; 1544 got = LENGTH (i);
1536 len -= got; 1545 } while (! interval_has_some_properties_list (properties, i));
1537 i = next_interval (i); 1546 }
1538 } 1547 /* Split away the beginning of this interval; what we don't
1539 /* Split away the beginning of this interval; what we don't 1548 want to modify. */
1540 want to modify. */ 1549 else if (i->position != s)
1541 else 1550 {
1542 { 1551 unchanged = i;
1543 unchanged = i; 1552 i = split_interval_right (unchanged, s - unchanged->position);
1544 i = split_interval_right (unchanged, s - unchanged->position); 1553 copy_properties (unchanged, i);
1545 copy_properties (unchanged, i);
1546 }
1547 } 1554 }
1548 1555
1549 /* We are at the beginning of an interval, with len to scan. 1556 /* We are at the beginning of an interval, with len to scan.