changeset 5187:b51c2079ec8e

Be much more careful about resizing a string argument, #'fill 2010-04-03 Aidan Kehoe <kehoea@parhasard.net> * fns.c (Ffill): Be much more careful about resizing a string argument, update pointers to within the string data that may have been relocated with the string resize. Fixes a test hang reported by Vin Shelton; thanks, Vin.
author Aidan Kehoe <kehoea@parhasard.net>
date Sat, 03 Apr 2010 15:27:32 +0100
parents b36d089cbed5
children 000287f8053b
files src/ChangeLog src/fns.c
diffstat 2 files changed, 24 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Apr 02 13:23:31 2010 +0100
+++ b/src/ChangeLog	Sat Apr 03 15:27:32 2010 +0100
@@ -1,3 +1,11 @@
+2010-04-03  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* fns.c (Ffill):
+	Be much more careful about resizing a string argument, update
+	pointers to within the string data that may have been relocated
+	with the string resize. Fixes a test hang reported by Vin Shelton;
+	thanks, Vin.
+
 2010-04-02  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* fns.c (FsortX, Ffill):
--- a/src/fns.c	Fri Apr 02 13:23:31 2010 +0100
+++ b/src/fns.c	Sat Apr 03 15:27:32 2010 +0100
@@ -3795,10 +3795,9 @@
  retry:
   if (STRINGP (sequence))
     {
-      Bytecount old_bytecount, new_bytecount, item_bytecount;
+      Bytecount prefix_bytecount, item_bytecount, delta;
       Ibyte item_buf[MAX_ICHAR_LEN];
-      Ibyte *p;
-      Ibyte *pend;
+      Ibyte *p, *pend;
 
       CHECK_CHAR_COERCE_INT (item);
 
@@ -3808,17 +3807,26 @@
 
       p = XSTRING_DATA (sequence);
       p = (Ibyte *) itext_n_addr (p, starting);
-      old_bytecount = p - XSTRING_DATA (sequence);
+      prefix_bytecount = p - XSTRING_DATA (sequence);
 
       ending = min (ending, string_char_length (sequence));
       pend = (Ibyte *) itext_n_addr (p, ending - starting); 
-
-      new_bytecount = old_bytecount + (item_bytecount * (ending - starting));
-      resize_string (sequence, -1, new_bytecount - old_bytecount);
+      delta = ((ending - starting) * item_bytecount) - (pend - p);
+
+      /* Resize the string if the bytecount for the area being modified is
+	 different. */
+      if (delta)
+	{
+	  resize_string (sequence, prefix_bytecount, delta);
+	  /* No need to zero-terminate the string, resize_string has done
+	     that for us. */
+	  p = XSTRING_DATA (sequence) + prefix_bytecount;
+	  pend = p + ((ending - starting) * item_bytecount);
+	}
 
       for (; p < pend; p += item_bytecount)
 	memcpy (p, item_buf, item_bytecount);
-      *p = '\0';
+
 
       init_string_ascii_begin (sequence);
       bump_string_modiff (sequence);