Hi,

Please, review the attached patch.  It should fix #1135, which is
related to string-copy! and affects at least the gap-buffer egg.

Best wishes.
Mario
-- 
http://parenteses.org/mario
>From 9bf82b9f523366c9795c0ad14c26bcb2f7c2b625 Mon Sep 17 00:00:00 2001
From: Mario Domenech Goulart <[email protected]>
Date: Fri, 27 Jun 2014 17:43:38 -0300
Subject: [PATCH] C_substring_copy: use C_memmove instead of C_memcpy

memcpy will screw things up when given the src and dest strings'
memory area overlap (e.g., the same string object is given as src and
dest argument), and that can cause problems in some string-copy! use
cases.

Fixes #1135.
---
 NEWS                    |    2 ++
 chicken.h               |    6 +++---
 tests/srfi-13-tests.scm |   12 ++++++++++++
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index a9ded9e..c8ce427 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@
   - Unit tcp now implicitly depends on ports instead of extras.
      This may break programs which don't use modules and forgot to
      require extras but use procedures from it.
+  - SRFI-13: fix string-copy! in cases source and destination strings'
+    memory areas overlap (#1135).
 
 - Unit lolevel:
   - Restore long-lost but still documented "vector-like?" procedure (#983)
diff --git a/chicken.h b/chicken.h
index 4a3c77a..f5a103e 100644
--- a/chicken.h
+++ b/chicken.h
@@ -1260,9 +1260,9 @@ extern double trunc(double);
 #define C_i_char_greater_or_equal_p(x, y)  C_mk_bool(C_character_code(x) >= C_character_code(y))
 #define C_i_char_less_or_equal_p(x, y)  C_mk_bool(C_character_code(x) <= C_character_code(y))
 #define C_substring_copy(s1, s2, start1, end1, start2) \
-                                        (C_memcpy((C_char *)C_data_pointer(s2) + C_unfix(start2), \
-                                                  (C_char *)C_data_pointer(s1) + C_unfix(start1), \
-                                                  C_unfix(end1) - C_unfix(start1) ), C_SCHEME_UNDEFINED)
+                                        (C_memmove((C_char *)C_data_pointer(s2) + C_unfix(start2), \
+                                                   (C_char *)C_data_pointer(s1) + C_unfix(start1), \
+                                                   C_unfix(end1) - C_unfix(start1) ), C_SCHEME_UNDEFINED)
 #define C_substring_compare(s1, s2, start1, start2, len) \
                                         C_mk_bool(C_memcmp((C_char *)C_data_pointer(s1) + C_unfix(start1), \
                                                            (C_char *)C_data_pointer(s2) + C_unfix(start2), \
diff --git a/tests/srfi-13-tests.scm b/tests/srfi-13-tests.scm
index 1262b82..8df378a 100644
--- a/tests/srfi-13-tests.scm
+++ b/tests/srfi-13-tests.scm
@@ -115,6 +115,18 @@
        (let ((x (string-copy "abcdefg")))
          (string-copy! x 2 "ZABCDEFG" 3 6)
          x))
+
+;; From Guile.  Thanks to Mark H Weaver.
+(test "string-copy!: overlapping src and dest, moving right"
+      "aabce"
+      (let ((str (string-copy "abcde")))
+	(string-copy! str 1 str 0 3) str))
+
+(test "string-copy!: overlapping src and dest, moving left"
+      "bcdde"
+      (let ((str (string-copy "abcde")))
+	(string-copy! str 0 str 1 4) str))
+
 (test "string-take" "Pete S"  (string-take "Pete Szilagyi" 6))
 (test "string-take" ""        (string-take "Pete Szilagyi" 0))
 (test "string-take" "Pete Szilagyi" (string-take "Pete Szilagyi" 13))
-- 
1.7.10.4

_______________________________________________
Chicken-hackers mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/chicken-hackers

Reply via email to