Skip to content

Commit 2e30f8d

Browse files
authored
[analyzer] Fix StreamChecker crash in fread modeling (#108393)
In #93408 69bc159 I refined how invalidation is done for `fread`. It can crash, if the "size" or "count" parameters of "fread" is a perfectly constrained negative value. In such cases, when it will try to allocate a SmallVector with a negative size, which will cause a crash. To mitigate this issue, let's just guard against negative values. CPP-3247
1 parent 8cf3eb4 commit 2e30f8d

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C,
11291129
if (!ElemTy.isNull() && CountVal && Size && StartIndexVal) {
11301130
int64_t NumBytesRead = Size.value() * CountVal.value();
11311131
int64_t ElemSizeInChars = Ctx.getTypeSizeInChars(ElemTy).getQuantity();
1132-
if (ElemSizeInChars == 0)
1132+
if (ElemSizeInChars == 0 || NumBytesRead < 0)
11331133
return nullptr;
11341134

11351135
bool IncompleteLastElement = (NumBytesRead % ElemSizeInChars) != 0;

clang/test/Analysis/fread.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,3 +443,33 @@ void test_unaligned_start_read(void) {
443443
fclose(fp);
444444
}
445445
}
446+
447+
void no_crash_if_count_is_negative(long l, long r, unsigned char *buffer) {
448+
FILE *fp = fopen("path", "r");
449+
if (fp) {
450+
if (l * r == -1) {
451+
fread(buffer, 1, l * r, fp); // no-crash
452+
}
453+
fclose(fp);
454+
}
455+
}
456+
457+
void no_crash_if_size_is_negative(long l, long r, unsigned char *buffer) {
458+
FILE *fp = fopen("path", "r");
459+
if (fp) {
460+
if (l * r == -1) {
461+
fread(buffer, l * r, 1, fp); // no-crash
462+
}
463+
fclose(fp);
464+
}
465+
}
466+
467+
void no_crash_if_size_and_count_are_negative(long l, long r, unsigned char *buffer) {
468+
FILE *fp = fopen("path", "r");
469+
if (fp) {
470+
if (l * r == -1) {
471+
fread(buffer, l * r, l * r, fp); // no-crash
472+
}
473+
fclose(fp);
474+
}
475+
}

0 commit comments

Comments
 (0)