Skip to content

[libc] Fix readlink tests on 32-bit systems #98168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 9, 2024

Conversation

mikhailramalho
Copy link
Member

This patch changes the call sizeof() to call malloc with the actual lenght of the string to allocate space for buf.

The test case worked in 64-bit systems because the sizeof(CString) was big enough (19 bytes) to hold the contents of FILENAME, but in 32-bit systems sizeof(CString) is only 12 bytes long, causing a truncation of FILENAME when placing it in buf.

I also changed the vla to a malloc instead to silence a "variable length arrays are a C99 feature [-Wvla-extension]" warning.

@llvmbot
Copy link
Member

llvmbot commented Jul 9, 2024

@llvm/pr-subscribers-libc

Author: Mikhail R. Gadelha (mikhailramalho)

Changes

This patch changes the call sizeof(<Cstring>) to call malloc with the actual lenght of the string to allocate space for buf.

The test case worked in 64-bit systems because the sizeof(CString) was big enough (19 bytes) to hold the contents of FILENAME, but in 32-bit systems sizeof(CString) is only 12 bytes long, causing a truncation of FILENAME when placing it in buf.

I also changed the vla to a malloc instead to silence a "variable length arrays are a C99 feature [-Wvla-extension]" warning.


Full diff: https://github.com/llvm/llvm-project/pull/98168.diff

3 Files Affected:

  • (modified) libc/test/src/unistd/CMakeLists.txt (+2)
  • (modified) libc/test/src/unistd/readlink_test.cpp (+8-4)
  • (modified) libc/test/src/unistd/readlinkat_test.cpp (+10-6)
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 1a1e01e50f4e8..332455b791aee 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -262,6 +262,7 @@ add_libc_unittest(
     libc.include.unistd
     libc.src.errno.errno
     libc.src.unistd.readlink
+    libc.src.string.string_utils
     libc.src.unistd.symlink
     libc.src.unistd.unlink
     libc.src.__support.CPP.string_view
@@ -279,6 +280,7 @@ add_libc_unittest(
     libc.include.unistd
     libc.src.errno.errno
     libc.src.unistd.readlinkat
+    libc.src.string.string_utils
     libc.src.unistd.symlink
     libc.src.unistd.unlink
     libc.src.__support.CPP.string_view
diff --git a/libc/test/src/unistd/readlink_test.cpp b/libc/test/src/unistd/readlink_test.cpp
index 49ab9c24f4024..e29a6bd3e374b 100644
--- a/libc/test/src/unistd/readlink_test.cpp
+++ b/libc/test/src/unistd/readlink_test.cpp
@@ -8,6 +8,7 @@
 
 #include "src/__support/CPP/string_view.h"
 #include "src/errno/libc_errno.h"
+#include "src/string/string_utils.h"
 #include "src/unistd/readlink.h"
 #include "src/unistd/symlink.h"
 #include "src/unistd/unlink.h"
@@ -30,17 +31,20 @@ TEST(LlvmLibcReadlinkTest, CreateAndUnlink) {
   //   3. Cleanup the symlink created in step #1.
   ASSERT_THAT(LIBC_NAMESPACE::symlink(LINK_VAL, LINK), Succeeds(0));
 
-  char buf[sizeof(LINK_VAL)];
-  ssize_t len = LIBC_NAMESPACE::readlink(LINK, buf, sizeof(buf));
+  size_t buf_len = LIBC_NAMESPACE::internal::string_length(FILENAME);
+  char *buf = static_cast<char *>(malloc(buf_len));
+  ssize_t len = LIBC_NAMESPACE::readlink(LINK, buf, buf_len);
   ASSERT_ERRNO_SUCCESS();
   ASSERT_EQ(cpp::string_view(buf, len), cpp::string_view(LINK_VAL));
 
   ASSERT_THAT(LIBC_NAMESPACE::unlink(LINK), Succeeds(0));
+  free(buf);
 }
 
 TEST(LlvmLibcReadlinkTest, ReadlinkInNonExistentPath) {
   using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
-  char buf[8];
-  ASSERT_THAT(LIBC_NAMESPACE::readlink("non-existent-link", buf, sizeof(buf)),
+  constexpr auto len = 8;
+  char buf[len];
+  ASSERT_THAT(LIBC_NAMESPACE::readlink("non-existent-link", buf, len),
               Fails(ENOENT));
 }
diff --git a/libc/test/src/unistd/readlinkat_test.cpp b/libc/test/src/unistd/readlinkat_test.cpp
index 7e1ded5f8a4a1..f2924d3b8f6c5 100644
--- a/libc/test/src/unistd/readlinkat_test.cpp
+++ b/libc/test/src/unistd/readlinkat_test.cpp
@@ -8,6 +8,7 @@
 
 #include "src/__support/CPP/string_view.h"
 #include "src/errno/libc_errno.h"
+#include "src/string/string_utils.h"
 #include "src/unistd/readlinkat.h"
 #include "src/unistd/symlink.h"
 #include "src/unistd/unlink.h"
@@ -32,18 +33,21 @@ TEST(LlvmLibcReadlinkatTest, CreateAndUnlink) {
   //   3. Cleanup the symlink created in step #1.
   ASSERT_THAT(LIBC_NAMESPACE::symlink(LINK_VAL, LINK), Succeeds(0));
 
-  char buf[sizeof(LINK_VAL)];
-  ssize_t len = LIBC_NAMESPACE::readlinkat(AT_FDCWD, LINK, buf, sizeof(buf));
+  size_t buf_len = LIBC_NAMESPACE::internal::string_length(FILENAME);
+  char *buf = static_cast<char *>(malloc(buf_len));
+  ssize_t len = LIBC_NAMESPACE::readlinkat(AT_FDCWD, LINK, buf, buf_len);
   ASSERT_ERRNO_SUCCESS();
   ASSERT_EQ(cpp::string_view(buf, len), cpp::string_view(LINK_VAL));
 
   ASSERT_THAT(LIBC_NAMESPACE::unlink(LINK), Succeeds(0));
+  free(buf);
 }
 
 TEST(LlvmLibcReadlinkatTest, ReadlinkInNonExistentPath) {
   using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
-  char buf[8];
-  ASSERT_THAT(LIBC_NAMESPACE::readlinkat(AT_FDCWD, "non-existent-link", buf,
-                                         sizeof(buf)),
-              Fails(ENOENT));
+  constexpr auto len = 8;
+  char buf[len];
+  ASSERT_THAT(
+      LIBC_NAMESPACE::readlinkat(AT_FDCWD, "non-existent-link", buf, len),
+      Fails(ENOENT));
 }

This patch removes the call sizeof(<Cstring>) and makes buf a
fixed-length array.

The test case worked in 64-bit systems because the sizeof(CString) was
big enough (19 bytes) to hold the contents of FILENAME, but in 32-bit
systems sizeof(CString) is only 12 bytes long, causing a truncation of
FILENAME when placing it in buf.
@mikhailramalho mikhailramalho merged commit 63a9662 into llvm:main Jul 9, 2024
4 of 5 checks passed
@mikhailramalho mikhailramalho deleted the fix-readlink branch July 9, 2024 20:18
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
This patch removes the call sizeof(<Cstring>) and makes buf a
fixed-length array.

The test case worked in 64-bit systems because the sizeof(CString) was
big enough (19 bytes) to hold the contents of FILENAME, but in 32-bit
systems sizeof(CString) is only 12 bytes long, causing a truncation of
FILENAME when placing it in buf.
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Aug 13, 2024
…97c5e1144

Local branch amd-gfx b4e97c5 Merged main:a1d73ace13a20ed122a66d3d59f0cbae58d0f669 into amd-gfx:df3bf34a3c95
Remote branch main 63a9662 [libc] Fix readlink tests on 32-bit systems (llvm#98168)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants