Skip to content

[clang][analyzer] Support 'fdopen' in the StreamChecker #76776

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
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1158,8 +1158,9 @@ Improvements
`0954dc3fb921 <https://github.com/llvm/llvm-project/commit/0954dc3fb9214b994623f5306473de075f8e3593>`_)

- Improved the ``alpha.unix.Stream`` checker by modeling more functions like,
``fflush``, ``fputs``, ``fgetc``, ``fputc``, ``fopen``, ``fopen``, ``fgets``.
(`#74296 <https://github.com/llvm/llvm-project/pull/74296>`_,
``fflush``, ``fputs``, ``fgetc``, ``fputc``, ``fopen``, ``fdopen``, ``fgets``, ``tmpfile``.
(`#76776 <https://github.com/llvm/llvm-project/pull/76776>`_,
`#74296 <https://github.com/llvm/llvm-project/pull/74296>`_,
`#73335 <https://github.com/llvm/llvm-project/pull/73335>`_,
`#72627 <https://github.com/llvm/llvm-project/pull/72627>`_,
`#71518 <https://github.com/llvm/llvm-project/pull/71518>`_,
Expand Down
1 change: 1 addition & 0 deletions clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class StreamChecker : public Checker<check::PreCall, eval::Call,
private:
CallDescriptionMap<FnDescription> FnDescriptions = {
{{{"fopen"}, 2}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
{{{"fdopen"}, 2}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
{{{"freopen"}, 3},
{&StreamChecker::preFreopen, &StreamChecker::evalFreopen, 2}},
{{{"tmpfile"}, 0}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
Expand Down
1 change: 1 addition & 0 deletions clang/test/Analysis/Inputs/system-header-simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ FILE *funopen(const void *,
int (*)(void *));

FILE *fopen(const char *restrict path, const char *restrict mode);
FILE *fdopen(int fd, const char *mode);
FILE *tmpfile(void);
FILE *freopen(const char *restrict pathname, const char *restrict mode, FILE *restrict stream);
int fclose(FILE *fp);
Expand Down
13 changes: 11 additions & 2 deletions clang/test/Analysis/stream-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ void error_fopen(void) {
fclose(F);
}

void error_fdopen(int fd) {
FILE *F = fdopen(fd, "r");
if (!F)
return;
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
fclose(F);
}

void error_freopen(void) {
FILE *F = fopen("file", "r");
if (!F)
Expand Down Expand Up @@ -146,8 +155,8 @@ void error_fgets(void) {
fgets(Buf, sizeof(Buf), F); // expected-warning {{Stream might be already closed}}
}

void error_fputc(void) {
FILE *F = tmpfile();
void error_fputc(int fd) {
FILE *F = fdopen(fd, "w");
if (!F)
return;
int Ret = fputc('X', F);
Expand Down
7 changes: 6 additions & 1 deletion clang/test/Analysis/stream-non-posix-function.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ typedef struct _FILE FILE;
// These functions are not standard C library functions.
FILE *tmpfile(const char *restrict path); // Real 'tmpfile' should have exactly 0 formal parameters.
FILE *fopen(const char *restrict path); // Real 'fopen' should have exactly 2 formal parameters.
FILE *fdopen(int fd); // Real 'fdopen' should have exactly 2 formal parameters.

void test_fopen_non_posix(void) {
FILE *fp = fopen("file"); // no-leak: This isn't the standard POSIX `fopen`, we don't know the semantics of this call.
}

void test_tmpfile_non_posix(void) {
FILE *fp = tmpfile("file"); // // no-leak: This isn't the standard POSIX `tmpfile`, we don't know the semantics of this call.
FILE *fp = tmpfile("file"); // no-leak: This isn't the standard POSIX `tmpfile`, we don't know the semantics of this call.
}

void test_fdopen_non_posix(int fd) {
FILE *fp = fdopen(fd); // no-leak: This isn't the standard POSIX `fdopen`, we don't know the semantics of this call.
}
10 changes: 10 additions & 0 deletions clang/test/Analysis/stream-note.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ void check_note_freopen(void) {
// expected-warning@-1 {{Opened stream never closed. Potential resource leak}}
// expected-note@-2 {{Opened stream never closed. Potential resource leak}}

void check_note_fdopen(int fd) {
FILE *F = fdopen(fd, "r"); // expected-note {{Stream opened here}}
if (!F)
// expected-note@-1 {{'F' is non-null}}
// expected-note@-2 {{Taking false branch}}
return;
}
// expected-warning@-1 {{Opened stream never closed. Potential resource leak}}
// expected-note@-2 {{Opened stream never closed. Potential resource leak}}

void check_note_leak_2(int c) {
FILE *F1 = fopen("foo1.c", "r"); // expected-note {{Stream opened here}}
// stdargs-note@-1 {{'fopen' is successful}}
Expand Down
8 changes: 8 additions & 0 deletions clang/test/Analysis/stream-stdlibraryfunctionargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ void test_fopen(void) {
// stdfunc-warning{{should not be NULL}}
}

void test_fdopen(int fd) {
FILE *fp = fdopen(fd, "r");
clang_analyzer_eval(fp != NULL); // any-warning{{TRUE}} any-warning{{FALSE}}
fclose(fp); // \
// stream-warning{{Stream pointer might be NULL}} \
// stdfunc-warning{{should not be NULL}}
}

void test_tmpfile(void) {
FILE *fp = tmpfile();
clang_analyzer_eval(fp != NULL); // any-warning{{TRUE}} any-warning{{FALSE}}
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Analysis/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ void f_open(void) {
fclose(p);
}

void f_dopen(int fd) {
FILE *F = fdopen(fd, "r");
char buf[1024];
fread(buf, 1, 1, F); // expected-warning {{Stream pointer might be NULL}}
fclose(F);
}

void f_seek(void) {
FILE *p = fopen("foo", "r");
if (!p)
Expand Down