Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,7 @@ tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C,
if (!ElemTy.isNull() && CountVal && Size && StartIndexVal) {
int64_t NumBytesRead = Size.value() * CountVal.value();
int64_t ElemSizeInChars = Ctx.getTypeSizeInChars(ElemTy).getQuantity();
if (ElemSizeInChars == 0)
if (ElemSizeInChars == 0 || NumBytesRead < 0)
return nullptr;

bool IncompleteLastElement = (NumBytesRead % ElemSizeInChars) != 0;
Expand Down
30 changes: 30 additions & 0 deletions clang/test/Analysis/fread.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,33 @@ void test_unaligned_start_read(void) {
fclose(fp);
}
}

void no_crash_if_count_is_negative(long s, unsigned char *buffer) {
FILE *fp = fopen("path", "r");
if (fp) {
if (s * s == -1) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: $s^2 = -1$ is mathematically impossible (even if we allow overflows: 0xffff...f $= (4^{k})^2 - 1$ where $k$ is the number of f digits and two consecutive integers that are >1 cannot be both perfect squares). I know that the static analyzer doesn't know this and will happily assume that s * s == -1 -- but it would be still nicer to use a different example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, I noticed that too. I figured it's a funny example, but refining it is also good.

fread(buffer, 1, s * s, fp); // no-crash
}
fclose(fp);
}
}

void no_crash_if_size_is_negative(long s, unsigned char *buffer) {
FILE *fp = fopen("path", "r");
if (fp) {
if (s * s == -1) {
fread(buffer, s * s, 1, fp); // no-crash
}
fclose(fp);
}
}

void no_crash_if_size_and_count_are_negative(long s, unsigned char *buffer) {
FILE *fp = fopen("path", "r");
if (fp) {
if (s * s == -1) {
fread(buffer, s * s, s * s, fp); // no-crash
}
fclose(fp);
}
}
Loading