With e.g.
$ cat test.c
#include <stdlib.h>
#include <string.h>
int main(void) {
char b[10];
char c = 'a';
strncpy(b, &c, 1);
free(strndup(&c, 1));
return 0;
}
$ clang -fsanitize=address -g test.c
$ ASAN_OPTIONS=strict_string_checks=1 ./a.out
=================================================================
==16283==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd8ec3f021 at pc 0x000000432cb6 bp 0x7ffd8ec3efd0 sp 0x7ffd8ec3e790
READ of size 7 at 0x7ffd8ec3f021 thread T0
#0 0x432cb5 in __interceptor_strndup /home/sbergman/github.com/llvm/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:485:3
#1 0x4dbe1a in main /home/sbergman/test.c:7:10
#2 0x7fcbd36ec58f in __libc_start_call_main (/lib64/libc.so.6+0x2d58f) (BuildId: 6e7b96dfb83f0bdcb6a410469b82f86415e5ada3)
#3 0x7fcbd36ec648 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x2d648) (BuildId: 6e7b96dfb83f0bdcb6a410469b82f86415e5ada3)
#4 0x41c384 in _start (/home/sbergman/a.out+0x41c384)
Address 0x7ffd8ec3f021 is located in stack of thread T0 at offset 65 in frame
#0 0x4dbcef in main /home/sbergman/test.c:3
This frame has 2 object(s):
[32, 42) 'b' (line 4)
[64, 65) 'c' (line 5) <== Memory access at offset 65 overflows this variable
apparently checks the &c
argument to strndup
for being an NTBS but not the one to strncpy
.
Is that deliberately so because strncpy
is a C standard function that is carefully defined to operate on arrays, while strndup
is a Posix extension that (accidentally?) claims that its argument must be a string?