[libc-commits] [libc] libc: strlcpy/strlcat shouldn't bzero the rest of `buf` (PR #114259)

George Burgess IV via libc-commits libc-commits at lists.llvm.org
Wed Oct 30 09:05:48 PDT 2024


https://github.com/gburgessiv created https://github.com/llvm/llvm-project/pull/114259

When running Bionic's testsuite over llvm-libc, tests broke because e.g.,

```
const char *str = "abc";
char buf[7]{"111111"};
strlcpy(buf, str, 7);
ASSERT_EQ(buf, {'1', '1', '1', '\0', '\0', '\0', '\0'});
```

On my machine (Debian w/ glibc and clang-16), a `printf` loop over `buf` gets unrolled into a series of const `printf` at compile-time:
```
printf("%d\n", '1');
printf("%d\n", '1');
printf("%d\n", '1');
printf("%d\n", 0);
printf("%d\n", '1');
printf("%d\n", '1');
printf("%d\n", 0);
```

Seems best to match existing precedent here.

>From 4b32b83a2b18ff1645ca47190abea240e31f5afc Mon Sep 17 00:00:00 2001
From: George Burgess IV <george.burgess.iv at gmail.com>
Date: Wed, 30 Oct 2024 09:40:03 -0600
Subject: [PATCH] libc: strlcpy/strlcat shouldn't bzero the rest of `buf`

When running Bionic's testsuite over llvm-libc, tests broke because
e.g.,

```
const char *str = "abc";
char buf[7]{"111111"};
strlcpy(buf, str, 7);
ASSERT_EQ(buf, {'1', '1', '1', '\0', '\0', '\0', '\0'});
```

On my machine (Debian w/ glibc and clang-16), a `printf` loop over `buf`
gets unrolled into a series of const `printf`` at compile-time:
```
printf("%d\n", '1');
printf("%d\n", '1');
printf("%d\n", '1');
printf("%d\n", 0);
printf("%d\n", '1');
printf("%d\n", '1');
printf("%d\n", 0);
```

Seems best to match existing precedent here.
---
 libc/src/string/string_utils.h        | 2 +-
 libc/test/src/string/strlcat_test.cpp | 9 +++++++++
 libc/test/src/string/strlcpy_test.cpp | 3 +--
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/libc/src/string/string_utils.h b/libc/src/string/string_utils.h
index 78381e46e480dd..240b28f15718a8 100644
--- a/libc/src/string/string_utils.h
+++ b/libc/src/string/string_utils.h
@@ -221,7 +221,7 @@ LIBC_INLINE size_t strlcpy(char *__restrict dst, const char *__restrict src,
     return len;
   size_t n = len < size - 1 ? len : size - 1;
   inline_memcpy(dst, src, n);
-  inline_bzero(dst + n, size - n);
+  dst[n] = '\0';
   return len;
 }
 
diff --git a/libc/test/src/string/strlcat_test.cpp b/libc/test/src/string/strlcat_test.cpp
index 1ffa4b0e921e2b..5757fc92b39d2a 100644
--- a/libc/test/src/string/strlcat_test.cpp
+++ b/libc/test/src/string/strlcat_test.cpp
@@ -27,6 +27,15 @@ TEST(LlvmLibcStrlcatTest, Smaller) {
   EXPECT_STREQ(buf, "abcd");
 }
 
+TEST(LlvmLibcStrlcatTest, SmallerNoOverwriteAfter0) {
+  const char *str = "cd";
+  char buf[8]{"ab\0\0efg"};
+
+  EXPECT_EQ(LIBC_NAMESPACE::strlcat(buf, str, 8), size_t(4));
+  EXPECT_STREQ(buf, "abcd");
+  EXPECT_STREQ(buf + 5, "fg");
+}
+
 TEST(LlvmLibcStrlcatTest, No0) {
   const char *str = "cd";
   char buf[7]{"ab"};
diff --git a/libc/test/src/string/strlcpy_test.cpp b/libc/test/src/string/strlcpy_test.cpp
index 5a1e30c12963f3..ecf0e925a265c3 100644
--- a/libc/test/src/string/strlcpy_test.cpp
+++ b/libc/test/src/string/strlcpy_test.cpp
@@ -25,6 +25,5 @@ TEST(LlvmLibcStrlcpyTest, Smaller) {
 
   EXPECT_EQ(LIBC_NAMESPACE::strlcpy(buf, str, 7), size_t(3));
   EXPECT_STREQ(buf, "abc");
-  for (const char *p = buf + 3; p < buf + 7; p++)
-    EXPECT_EQ(*p, '\0');
+  EXPECT_STREQ(buf + 4, "11");
 }



More information about the libc-commits mailing list