Skip to content

[libc] Expand usage of libc null checks. #116262

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 59 commits into from
Jun 4, 2025

Conversation

AlyElashram
Copy link
Contributor

@AlyElashram AlyElashram commented Nov 14, 2024

Fixes #111546

@AlyElashram AlyElashram changed the title Expand usage of libc null checks [libc] Expand usage of libc null checks. Dec 13, 2024
@AlyElashram AlyElashram force-pushed the Expand-usage-of-libc-null-checks branch from e895dce to f7da133 Compare December 13, 2024 16:53
@AlyElashram AlyElashram marked this pull request as ready for review December 13, 2024 16:53
@AlyElashram AlyElashram marked this pull request as draft December 13, 2024 20:34
@AlyElashram
Copy link
Contributor Author

Hey @nickdesaulniers , I'm done with the changes however I'm currently creating unit tests to check that the functions segfault correctly. I'm failing to catch the segfault gracefully. Here's my current implementation which segfaults and coredumps for the memchr.cpp function.

#include "hdr/signal_macros.h"

TEST(LlvmLibcMemChrTest, CrashOnNullPtr) {
    LIBC_NAMESPACE::memchr(nullptr, 1, 1);
}

I tried the ASSERT_DEATH(LIBC_NAMESPACE::memchr(nullptr,1,1), WITH_SIGNAL(SIGSEGV)); macro but it causes linking errors.

@nickdesaulniers nickdesaulniers self-requested a review December 18, 2024 21:55
@nickdesaulniers
Copy link
Member

but it causes linking errors.

What's the error you observe? The precommit bot is pointing out:

/home/runner/work/llvm-project/llvm-project/libc/src/stdio/fscanf.cpp:25:3: error: variable has incomplete type 'volatile ::FILE' (aka 'volatile FILE')
   25 |   LIBC_CRASH_ON_NULLPTR(stream);
      |   ^
/home/runner/work/llvm-project/llvm-project/libc/src/__support/macros/null_check.h:23:38: note: expanded from macro 'LIBC_CRASH_ON_NULLPTR'
   23 |       [[maybe_unused]] volatile auto crash = *crashing;                        \
      |                                      ^
/home/runner/work/llvm-project/llvm-project/libc/include/llvm-libc-types/FILE.h:12:16: note: forward declaration of 'FILE'
   12 | typedef struct FILE FILE;
      |                ^

which isn't a linkage failure.

@AlyElashram
Copy link
Contributor Author

What's the error you observe? The precommit bot is pointing out:

I reverted the changes in the functions that were failing in the prebuilt commit , My only failures now are in the tests.

Here is the test I'm trying out , the test is added inside memchr_test.cpp:

#include "hdr/signal_macros.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcMemChrTest, CrashOnNullPtr) {
  ASSERT_DEATH([](){ LIBC_NAMESPACE::memchr(nullptr, 1, 1); } , WITH_SIGNAL(SIGSEGV));
}

Here is the result of the test :

[1908/2035] Linking CXX executable libc/test/src/string/libc.test.src.string.memchr_test.__hermetic__.__build__
FAILED: libc/test/src/string/libc.test.src.string.memchr_test.__hermetic__.__build__ 
: && /usr/bin/clang++ -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -g -nolibc -nostartfiles -nostdlib++ -static libc/startup/linux/crt1.o libc/test/src/string/CMakeFiles/libc.test.src.string.memchr_test.__hermetic__.__build__.dir/memchr_test.cpp.o -o libc/test/src/string/libc.test.src.string.memchr_test.__hermetic__.__build__  libc/test/UnitTest/libLibcTest.hermetic.a  libc/test/UnitTest/libLibcHermeticTestSupport.hermetic.a  libc/test/src/string/liblibc.test.src.string.memchr_test.__hermetic__.libc.a && :
/usr/bin/ld: libc/test/src/string/CMakeFiles/libc.test.src.string.memchr_test.__hermetic__.__build__.dir/memchr_test.cpp.o: in function `LlvmLibcMemChrTest_CrashOnNullPtr::Run()':
/home/aly/llvm-project/libc/test/src/string/memchr_test.cpp:127:(.text+0xcb2): undefined reference to `__llvm_libc_20_0_0_git::testing::Test::testProcessKilled(__llvm_libc_20_0_0_git::testutils::FunctionCaller*, int, char const*, char const*, __llvm_libc_20_0_0_git::testing::internal::Location)'
/usr/bin/ld: libc/test/src/string/libc.test.src.string.memchr_test.__hermetic__.__build__: hidden symbol `_ZN22__llvm_libc_20_0_0_git7testing4Test17testProcessKilledEPNS_9testutils14FunctionCallerEiPKcS6_NS0_8internal8LocationE' isn't defined
/usr/bin/ld: final link failed: bad value
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

What I understand from the error is that it's not seeing the ASSERT_DEATH macro , but i'm not sure why since the test.h file is included.
@nickdesaulniers

@nickdesaulniers
Copy link
Member

@michaelrj-google pointed out to me that any tests that you add usage of EXPECT_DEATH or ASSERT_DEATH, you'll need to add UNIT_TEST_ONLY to their cmake add_libc_test invocation.

Example:

Sounds like that should disable the hermetic test for that function, which is probably fine.

Copy link

github-actions bot commented Dec 22, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@AlyElashram AlyElashram marked this pull request as ready for review December 27, 2024 13:39
@nickdesaulniers
Copy link
Member

#123401 has been merged; please rebase on top of that. Then you can drop the extra temporary variables.

@AlyElashram
Copy link
Contributor Author

#123401 has been merged; please rebase on top of that. Then you can drop the extra temporary variables.

Will patch it first thing tomorrow, I'll also remove checking for the signal and just leave the expect_death macro

@AlyElashram AlyElashram force-pushed the Expand-usage-of-libc-null-checks branch from bed04e1 to 130bc73 Compare January 26, 2025 14:44
@lntue
Copy link
Contributor

lntue commented Apr 17, 2025

@AlyElashram do you mind syncing the PR to resolve conflicts?

@AlyElashram
Copy link
Contributor Author

@lntue can you please check the tests out when you have the time 👀

@AlyElashram AlyElashram force-pushed the Expand-usage-of-libc-null-checks branch from 5d49deb to e6a336f Compare May 30, 2025 22:42
#include <stddef.h>

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(void *, memrchr, (const void *src, int c, size_t n)) {
LIBC_CRASH_ON_NULLPTR(src);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check if n != 0 before checking nullptr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions are not mentioned in this doc here , but they are different variants of the same function.

memrchr for example , is a variant of memchr and memchr is mentioned in the doc.

I'm not sure if we should include the variants or follow the document strictly @lntue .

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions are probably GNU or BSD extensions and are not specified in the C standards, so technically we can define any behavior that we think it makes sense. Nonetheless, the implementation below is not UB and well-behaved when n = 0, in addition to being consistent with memchr.

ASSERT_DEATH([]() { LIBC_NAMESPACE::memcpy(nullptr, nullptr, 1); },
WITH_SIGNAL(-1));
}
#endif // defined(LIBC_TARGET_OS_IS_LINUX)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: You might want to do mass update the comments.

@@ -18,6 +19,10 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, mempcpy,
(void *__restrict dst, const void *__restrict src,
size_t count)) {
if (count) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a count check here , for consistency with memcpy and also since memcpy and mempcpy are well behaved at n = 0
@lntue

@lntue lntue merged commit ff844df into llvm:main Jun 4, 2025
15 of 16 checks passed
@AlyElashram
Copy link
Contributor Author

AlyElashram commented Jun 6, 2025

@lntue the unit tests are generating failures here that I don't understand. I'm not sure if this should've been merged. They generated errors that are also affecting all other PRs.

I traced back the errors and they only occur on this PR , and not #142085

Failure in question :

[6320/6668] Running unit test libc.test.src.string.memcmp_opt_host_test.__unit__
FAILED: projects/libc/test/src/string/CMakeFiles/libc.test.src.string.memcmp_opt_host_test.__unit__ /home/gha/actions-runner/_work/llvm-project/llvm-project/build/projects/libc/test/src/string/CMakeFiles/libc.test.src.string.memcmp_opt_host_test.__unit__ 

@lntue
Copy link
Contributor

lntue commented Jun 6, 2025

@lntue the unit tests are generating failures here that I don't understand. I'm not sure if this should've been merged. They generated errors that are also affecting all other PRs.

I traced back the errors and they only occur on this PR , and not #142085

Failure in question :

[6320/6668] Running unit test libc.test.src.string.memcmp_opt_host_test.__unit__
FAILED: projects/libc/test/src/string/CMakeFiles/libc.test.src.string.memcmp_opt_host_test.__unit__ /home/gha/actions-runner/_work/llvm-project/llvm-project/build/projects/libc/test/src/string/CMakeFiles/libc.test.src.string.memcmp_opt_host_test.__unit__ 

bzero and bcmp tests also failed in the precommit CI for similar errors (Illegal instructions on SizeSweep tests). Those 2 are not related to your change at all. Also post commit CIs are happy with the change, and right now I cannot reproduce these failures locally. It's probably for other reasons than this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc] Expand usage of LIBC_ADD_NULL_CHECKS.
4 participants