summaryrefslogtreecommitdiff
path: root/src/string
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-09-23 00:03:08 -0400
committerRich Felker <dalias@aerifal.cx>2018-09-23 00:03:08 -0400
commitdebadaa238e90fce897b467a9efefcbbc0155d06 (patch)
tree36922273f94c2bba55e05f09ac4997ace0522017 /src/string
parentc50985d5c8e316c5c464f352e79eeebfed1121a9 (diff)
downloadmusl-debadaa238e90fce897b467a9efefcbbc0155d06.tar.gz
fix undefined pointer comparison in memmove
the comparison must take place in the address space model as an integer type, since comparing pointers that are not pointing into the same array is undefined. the subsequent d<s comparison however is valid, because it's only reached in the case where the source and dest overlap, in which case they are necessarily pointing to parts of the same array. to make the comparison, use an unsigned range check for dist(s,d)>=n, algebraically !(-n<s-d<n). subtracting n yields !(-2*n<s-d-n<0), which mapped into unsigned modular arithmetic is !(-2*n<s-d-n) or rather -2*n>=s-d-n.
Diffstat (limited to 'src/string')
-rw-r--r--src/string/memmove.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/string/memmove.c b/src/string/memmove.c
index 27f670e1..f225bb30 100644
--- a/src/string/memmove.c
+++ b/src/string/memmove.c
@@ -10,7 +10,7 @@ void *memmove(void *dest, const void *src, size_t n)
const char *s = src;
if (d==s) return d;
- if (s+n <= d || d+n <= s) return memcpy(d, s, n);
+ if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n);
if (d<s) {
if ((uintptr_t)s % WS == (uintptr_t)d % WS) {