xref: /rk3399_ARM-atf/lib/libc/memmove.c (revision 4661abc7c44926ac34ce96deb9e332a6804a2520)
1*4661abc7SAntonio Nino Diaz /*
2*4661abc7SAntonio Nino Diaz  * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
3*4661abc7SAntonio Nino Diaz  *
4*4661abc7SAntonio Nino Diaz  * SPDX-License-Identifier: BSD-3-Clause
5*4661abc7SAntonio Nino Diaz  */
6*4661abc7SAntonio Nino Diaz 
7*4661abc7SAntonio Nino Diaz #include <string.h>
8*4661abc7SAntonio Nino Diaz 
9*4661abc7SAntonio Nino Diaz void *memmove(void *dst, const void *src, size_t len)
10*4661abc7SAntonio Nino Diaz {
11*4661abc7SAntonio Nino Diaz 	/*
12*4661abc7SAntonio Nino Diaz 	 * The following test makes use of unsigned arithmetic overflow to
13*4661abc7SAntonio Nino Diaz 	 * more efficiently test the condition !(src <= dst && dst < str+len).
14*4661abc7SAntonio Nino Diaz 	 * It also avoids the situation where the more explicit test would give
15*4661abc7SAntonio Nino Diaz 	 * incorrect results were the calculation str+len to overflow (though
16*4661abc7SAntonio Nino Diaz 	 * that issue is probably moot as such usage is probably undefined
17*4661abc7SAntonio Nino Diaz 	 * behaviour and a bug anyway.
18*4661abc7SAntonio Nino Diaz 	 */
19*4661abc7SAntonio Nino Diaz 	if ((size_t)dst - (size_t)src >= len) {
20*4661abc7SAntonio Nino Diaz 		/* destination not in source data, so can safely use memcpy */
21*4661abc7SAntonio Nino Diaz 		return memcpy(dst, src, len);
22*4661abc7SAntonio Nino Diaz 	} else {
23*4661abc7SAntonio Nino Diaz 		/* copy backwards... */
24*4661abc7SAntonio Nino Diaz 		const char *end = dst;
25*4661abc7SAntonio Nino Diaz 		const char *s = (const char *)src + len;
26*4661abc7SAntonio Nino Diaz 		char *d = (char *)dst + len;
27*4661abc7SAntonio Nino Diaz 		while (d != end)
28*4661abc7SAntonio Nino Diaz 			*--d = *--s;
29*4661abc7SAntonio Nino Diaz 	}
30*4661abc7SAntonio Nino Diaz 	return dst;
31*4661abc7SAntonio Nino Diaz }
32