summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-07-05 07:45:58 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-07-05 07:45:58 -0700
commit3182bdf1e39559179c8e7f97ea9eb5f4bff0ef7f (patch)
tree128bff8650f4f35a265123baf96a9b6f0bf76919
parentaa179ce68abcefc3edd30f01cdde35461af9cc2f (diff)
downloadtxr-3182bdf1e39559179c8e7f97ea9eb5f4bff0ef7f.tar.gz
txr-3182bdf1e39559179c8e7f97ea9eb5f4bff0ef7f.tar.bz2
txr-3182bdf1e39559179c8e7f97ea9eb5f4bff0ef7f.zip
replace: deal with overlapping.
* buf.c (replace_buf): In the same-type case, use memmove rather than memcpy in case the objects overlap, so we don't invoke C undefined behavior. * lib.c (replace_str, replace_vec): Likewise. * txr.1: Specify that if the replacement sequence overlaps with the target range of the destination sequence, or with any portion that has to be relocated if range changes size, then the behavior is unspecified.
-rw-r--r--buf.c2
-rw-r--r--lib.c6
-rw-r--r--txr.112
3 files changed, 16 insertions, 4 deletions
diff --git a/buf.c b/buf.c
index d95a9033..928eaece 100644
--- a/buf.c
+++ b/buf.c
@@ -339,7 +339,7 @@ val replace_buf(val buf, val items, val from, val to)
if (zerop(len_it))
return buf;
if (bufp(items)) {
- memcpy(buf->b.data + c_num(from), items->b.data, c_num(len_it));
+ memmove(buf->b.data + c_num(from), items->b.data, c_num(len_it));
} else {
seq_iter_t item_iter;
seq_iter_init(self, &item_iter, items);
diff --git a/lib.c b/lib.c
index 13a41947..1e7d8885 100644
--- a/lib.c
+++ b/lib.c
@@ -3857,7 +3857,7 @@ val replace_str(val str_in, val items, val from, val to)
if (zerop(len_it))
return str_in;
if (stringp(items)) {
- wmemcpy(str_in->st.str + c_num(from), c_str(items), c_num(len_it));
+ wmemmove(str_in->st.str + c_num(from), c_str(items), c_num(len_it));
} else {
seq_iter_t item_iter;
seq_iter_init(self, &item_iter, items);
@@ -7289,8 +7289,8 @@ val replace_vec(val vec_in, val items, val from, val to)
if (zerop(len_it))
return vec_in;
if (vectorp(items)) {
- memcpy(vec_in->v.vec + c_num(from), items->v.vec,
- sizeof *vec_in->v.vec * c_num(len_it));
+ memmove(vec_in->v.vec + c_num(from), items->v.vec,
+ sizeof *vec_in->v.vec * c_num(len_it));
mut(vec_in);
} else {
seq_iter_t item_iter;
diff --git a/txr.1 b/txr.1
index a8eb365c..5bdf24a6 100644
--- a/txr.1
+++ b/txr.1
@@ -28195,6 +28195,18 @@ be monotonically increasing, after consideration of the
displacement of negative values.
If
+.meta replacement-sequence
+shares storage with the target range of
+.metn sequence ,
+or, in the case when that range is resized by the
+.code replace
+operation, shares storage with any portion of
+.meta sequence
+above that range, then the effect of
+.code replace
+on either object is unspecified.
+
+If
.meta sequence
is a
.code carray