Open
Description
Glibc commit Implement strlcpy and strlcat.
Built environment
$ clang -v
clang version 18.1.8 (Fedora 18.1.8-1.fc40)
Target: x86_64-redhat-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Configuration file: /etc/clang/x86_64-redhat-linux-gnu-clang.cfg
System configuration file directory: /etc/clang/
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/14
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/14
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
$ ldd --version
ldd (GNU libc) 2.39
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
$ uname -a
Linux fedora 6.11.4-201.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Oct 20 15:04:22 UTC 2024 x86_64 GNU/Linux
test code
/* msan_strlcpy_test.c */
#include <stdio.h>
#include <string.h>
// https://sourceware.org/git/?p=glibc.git;a=blob;f=string/strlcpy.c;h=c6c33b1e33d601c66776ea6eec1b0c8f8ed696a9;hb=ef321e23c20eebc6d6fb4044425c00e6df27b05f
size_t
__strlcpy (char *__restrict dest, const char *__restrict src, size_t size)
{
size_t src_length = strlen (src);
if (__glibc_unlikely (src_length >= size))
{
if (size > 0)
{
/* Copy the leading portion of the string. The last
character is subsequently overwritten with the NUL
terminator, but the destination size is usually a
multiple of a small power of two, so writing it twice
should be more efficient than copying an odd number of
bytes. */
memcpy (dest, src, size);
dest[size - 1] = '\0';
}
}
else
/* Copy the string and its terminating NUL character. */
memcpy (dest, src, src_length + 1);
return src_length;
}
int main()
{
char defname[256];
// The program won't crash here
memset(defname, 0x00, 4);
for (int i = 0; i < 4; i++) {
printf("%02x ", defname[i]);
}
printf("\n");
// The program won't crash here
strncpy(defname, "AAAAAAAA", 8);
for (int i = 0; i < 8; i++) {
printf("%02x ", defname[i]);
}
printf("\n");
// The program won't crash here
__strlcpy(defname, "AAAAAAAAAAAA", 12);
for (int i = 0; i < 12; i++) {
printf("%02x ", defname[i]);
}
printf("\n");
// The program shouldn't crash, But it dose;
strlcpy(defname, "AAAAAAAAAAAAAAAA", 16);
for (int i = 0; i < 16; i++) {
printf("%02x ", defname[i]);
}
printf("\n");
}
compile and run
$ clang -fsanitize=memory msan_strlcpy_test.c -o msan_strlcpy_test
$ ./msan_strlcpy_test
00 00 00 00
41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41 00
==154959==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x4c8d6d in main (/home/down/Desktop/msan_strlcpy_test+0x4c8d6d) (BuildId: 90183bc646d4995b7cd61af36dece204d375dd3e)
#1 0x7f03337af087 in __libc_start_call_main (/lib64/libc.so.6+0x2a087) (BuildId: 77c77fee058b19c6f001cf2cb0371ce3b8341211)
#2 0x7f03337af14a in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x2a14a) (BuildId: 77c77fee058b19c6f001cf2cb0371ce3b8341211)
#3 0x430304 in _start (/home/down/Desktop/msan_strlcpy_test+0x430304) (BuildId: 90183bc646d4995b7cd61af36dece204d375dd3e)
SUMMARY: MemorySanitizer: use-of-uninitialized-value (/home/down/Desktop/msan_strlcpy_test+0x4c8d6d) (BuildId: 90183bc646d4995b7cd61af36dece204d375dd3e) in main
Exiting
Ping @vitalybuka