testing/libc/arch_libc: Fix out-of-bounds write in memmove test.

The adjacent overlap case in test_memmove() placed the source at a fixed
g_buf1 + align + 64 and the destination one size further, so the
destination tail reached align + 64 + 2 * size.  g_buf1 is only
TEST_BUF_SIZE + MAX_ALIGN (528) bytes, so the larger swept sizes ran off
the end: align=0 with size=255 writes up to offset 573, that is 46 bytes
past the object.  AddressSanitizer aborted arch_libctest with a
global-buffer-overflow.

Start the adjacent layout at g_buf1 + align instead.  The tail then
reaches align + 2 * size, which is at most 7 + 2 * 257 = 521 and stays
inside g_buf1 for every alignment and boundary size that is swept, while
still keeping source and destination exactly adjacent.

Impact: test only, selected by CONFIG_TESTING_ARCH_LIBC (default n).

Testing: built and ran sim:nsh on Linux x86_64 (Ubuntu 24.04,
gcc 13.3.0) with CONFIG_TESTING_ARCH_LIBC=y.  memmove reports PASSED
with no sanitizer report, and "arch_libc_test Passed".

Assisted-by: Claude:claude-opus-5
Signed-off-by: dengwenqi <dengwenqi@xiaomi.com>
This commit is contained in:
dengwenqi 2026-07-06 21:59:03 +08:00 committed by Alan C. Assis
parent 0b3049b6ca
commit 7043f96fef

View file

@ -193,14 +193,21 @@ static int test_memmove(void)
fail++;
}
/* Adjacent (no overlap): dst = src + size */
/* Adjacent (no overlap): dst = src + size.
* The destination tail reaches align + 2*size, so the base
* offset must satisfy align + 2*size <= sizeof(g_buf1); a
* fixed +64 base overflows g_buf1 for the larger boundary
* sizes (e.g. size=255, align=0 writes 45 bytes past the
* end), which AddressSanitizer flags as a global-buffer-
* overflow. Start from g_buf1 + align instead.
*/
fill_pattern(g_buf1 + align + 64, size);
memcpy(g_buf2 + align + 64, g_buf1 + align + 64, size);
memmove(g_buf1 + align + 64 + size,
g_buf1 + align + 64, size);
if (memcmp(g_buf1 + align + 64 + size,
g_buf2 + align + 64, size) != 0)
fill_pattern(g_buf1 + align, size);
memcpy(g_buf2 + align, g_buf1 + align, size);
memmove(g_buf1 + align + size,
g_buf1 + align, size);
if (memcmp(g_buf1 + align + size,
g_buf2 + align, size) != 0)
{
printf(" FAIL adjacent: align=%d size=%d\n", align, size);
fail++;