-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
[SanitizerCommon] add null check for fopen64 interceptor #68760
Conversation
Hi @kcc , I don't have access to add reviewers, could you please review this patch? Thanks. |
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Wu Yingcong (yingcong-wu) ChangesCurrently, the interceptor for fopen64 will crash when path is null. Adding the same null check as Full diff: https://github.com/llvm/llvm-project/pull/68760.diff 2 Files Affected:
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 80efaf54a0607f6..4da29d928fcc236 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -6145,7 +6145,7 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
__sanitizer_FILE *res = REAL(fopen64)(path, mode);
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
diff --git a/compiler-rt/test/sanitizer_common/TestCases/fopen64_nullptr.c b/compiler-rt/test/sanitizer_common/TestCases/fopen64_nullptr.c
new file mode 100644
index 000000000000000..2c260865c80a792
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/fopen64_nullptr.c
@@ -0,0 +1,9 @@
+// Check that fopen64(NULL, "r") is ok.
+// `-m32` and `-D_FILE_OFFSET_BITS=64` will make fopen() call fopen64()
+
+// REQUIRES: asan
+// RUN: %clang -m32 -D_FILE_OFFSET_BITS=64 -O2 %s -o %t && %run %t
+#include <stdio.h>
+const char *fn = NULL;
+FILE *f;
+int main() { f = fopen(fn, "r"); }
|
My test is not well-written. I don't know how fopen64() is used in other systems, so I don't know if I can test fopen64() directly. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
@@ -0,0 +1,8 @@ | |||
// Check that fopen64(NULL, "r") is ok. | |||
|
|||
// REQUIRES: linux |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The interceptors file defines
#define SANITIZER_INTERCEPT_FOPEN64 (SI_GLIBC || SI_SOLARIS32)
so // REQUIRES: glibc
might be a safer bet? (and technically solaris32, but no one will notice). Not all Linux builds will have glibc.
After adding back the 'RUN' command but not making the interceptor change:
This is good: your test resulted in a failure when the interceptor code is wrong After also making the interceptor change:
so I think it also needs something like:
or you could try changing the compilation options to remove the 32-bit build (haven't tried it myself). |
https://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html says "The fopen() function shall open the file whose pathname is the string pointed to by pathname, and associates a stream with it." A null argument cannot be used and the behavior is undefined. I cannot find historical documented precedent for accepting a null argument in https://www.kernel.org/doc/man-pages/ and elsewhere. There are many places that we don't check null arguments for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.
Since it's UB, we can do whatever we like, so accepting the null argument is not technically wrong, right? Alternatively, would you be satisfied if the interceptor were changed to return an error in such cases? I don't like the status quo (i.e., without this patch), whereby the interceptor will dereference a null pointer (e.g., output in #68760 (comment)), because it's not an intuitive error message. |
Thank you @thurstond for your help. I added back the RUN line and add requires for asan and glibc. I think we should add this since we already have added a null check for fopen() in https://github.com/intel-restricted/applications.compilers.llvm-project/commit/1d1be3dd8822c18babbebdcc60d4bbf152df5607. |
Closed as reviewer rejected. |
Currently, the interceptor for fopen64 will crash when path is null. Adding the same null check as
fopen()
.