llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Radovan Božić (bozicrHT) <details> <summary>Changes</summary> Add missing `-Wforitfy-source` diagnostics for `fread`, `fwrite`, and `fgets`. This continues the work from #<!-- -->142230. --- Full diff: https://github.com/llvm/llvm-project/pull/204337.diff 4 Files Affected: - (modified) clang/include/clang/Basic/Builtins.td (+5) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5) - (modified) clang/lib/Sema/SemaChecking.cpp (+37) - (modified) clang/test/Sema/warn-fortify-source.c (+14) ``````````diff diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 053a257ba6d4a..81f1d1011911e 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3510,6 +3510,11 @@ def Fwrite : LibBuiltin<"stdio.h"> { let Prototype = "size_t(void const*, size_t, size_t, FILE*)"; } +def Fgets : LibBuiltin<"stdio.h"> { + let Spellings = ["fgets"]; + let Prototype = "char*(char*, int, FILE*)"; +} + // C99 ctype.h def IsAlNum : LibBuiltin<"ctype.h"> { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f84cd8dca6d4c..6daa810488242 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1002,6 +1002,11 @@ def warn_fortify_scanf_overflow : Warning< "%2, but the corresponding specifier may require size %3">, InGroup<FortifySource>; +def warn_fortify_source_overread : Warning< + "'%0' will always read past the source buffer; source buffer has " + "size %1, but size argument is %2">, + InGroup<FortifySource>; + def err_function_start_invalid_type: Error< "argument must be a function">; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b8a3f48a32f24..c57733034b10b 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1232,6 +1232,25 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, return std::nullopt; }; + auto ComputeExplicitObjectSizeArgumentProduct = + [&](unsigned LIndex, unsigned RIndex) -> std::optional<llvm::APSInt> { + auto L = ComputeExplicitObjectSizeArgument(LIndex); + auto R = ComputeExplicitObjectSizeArgument(RIndex); + if (!L || !R) + return std::nullopt; + + unsigned W = + 2 * std::max({L->getBitWidth(), R->getBitWidth(), SizeTypeWidth}); + + llvm::APSInt LE = L->extOrTrunc(W); + llvm::APSInt RE = R->extOrTrunc(W); + + LE.setIsUnsigned(true); + RE.setIsUnsigned(true); + + return LE * RE; + }; + auto ComputeStrLenArgument = [&](unsigned Index) -> std::optional<llvm::APSInt> { std::optional<unsigned> IndexOptional = TranslateIndex(Index); @@ -1433,6 +1452,24 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, DestinationSize = ComputeSizeArgument(1); break; } + case Builtin::BIfread: { + DiagID = diag::warn_fortify_source_overflow; + SourceSize = ComputeExplicitObjectSizeArgumentProduct(1, 2); + DestinationSize = ComputeSizeArgument(0); + break; + } + case Builtin::BIfwrite: { + DiagID = diag::warn_fortify_source_overread; + SourceSize = ComputeExplicitObjectSizeArgumentProduct(1, 2); + DestinationSize = ComputeSizeArgument(0); + break; + } + case Builtin::BIfgets: { + DiagID = diag::warn_fortify_source_size_mismatch; + SourceSize = ComputeExplicitObjectSizeArgument(1); + DestinationSize = ComputeSizeArgument(0); + break; + } case Builtin::BIsnprintf: case Builtin::BI__builtin_snprintf: case Builtin::BIvsnprintf: diff --git a/clang/test/Sema/warn-fortify-source.c b/clang/test/Sema/warn-fortify-source.c index d0b519a516545..89f1f25773514 100644 --- a/clang/test/Sema/warn-fortify-source.c +++ b/clang/test/Sema/warn-fortify-source.c @@ -9,6 +9,8 @@ // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS -fexperimental-new-constant-interpreter typedef unsigned long size_t; +typedef struct _IO_FILE FILE; + #ifdef __cplusplus extern "C" { @@ -23,6 +25,10 @@ void *memcpy(void *dst, const void *src, size_t c); #endif void bcopy(const void *src, void *dst, size_t n); void bzero(void *dst, size_t n); +size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +char *fgets(char *s, int size, FILE *stream); + #ifdef __cplusplus } @@ -116,6 +122,14 @@ void call_bcopy_bzero(void) { __builtin_bzero(dst, 11); // expected-warning {{'bzero' will always overflow; destination buffer has size 10, but size argument is 11}} } +void call_fread_fwrite_fgets(FILE *fp) { + char src[4]; + fread(src, 2, 3, fp); // expected-warning {{'fread' will always overflow; destination buffer has size 4, but size argument is 6}} + fwrite(src, 2, 3, fp); // expected-warning {{'fwrite' will always read past the source buffer; source buffer has size 4, but size argument is 6}} + fgets(src, 5, fp); // expected-warning {{'fgets' size argument is too large; destination buffer has size 4, but size argument is 5}} + +} + void call_snprintf(double d, int n) { char buf[10]; __builtin_snprintf(buf, 10, "merp"); `````````` </details> https://github.com/llvm/llvm-project/pull/204337 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
