This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG0954dc3fb921: [analyzer] CStringChecker buffer access checks should check the first bytes (authored by steakhal).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D159109/new/ https://reviews.llvm.org/D159109 Files: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp clang/test/Analysis/string.c Index: clang/test/Analysis/string.c =================================================================== --- clang/test/Analysis/string.c +++ clang/test/Analysis/string.c @@ -71,6 +71,7 @@ int scanf(const char *restrict format, ...); void *malloc(size_t); void free(void *); +void *memcpy(void *dest, const void *src, unsigned long n); //===----------------------------------------------------------------------=== // strlen() @@ -1713,3 +1714,21 @@ free(dataBuffer); } #endif + +#ifndef SUPPRESS_OUT_OF_BOUND +void CWE124_Buffer_Underwrite__malloc_char_memcpy() { + char * dataBuffer = (char *)malloc(100*sizeof(char)); + if (dataBuffer == NULL) return; + memset(dataBuffer, 'A', 100-1); + dataBuffer[100-1] = '\0'; + char *data = dataBuffer - 8; + + char source[100]; + memset(source, 'C', 100-1); // fill with 'C's + source[100-1] = '\0'; // null terminate + + memcpy(data, source, 100*sizeof(char)); // expected-warning {{Memory copy function overflows the destination buffer}} + data[100-1] = '\0'; + free(dataBuffer); +} +#endif Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -480,6 +480,14 @@ if (!Filter.CheckCStringOutOfBounds) return State; + SVal BufStart = + svalBuilder.evalCast(BufVal, PtrTy, Buffer.Expression->getType()); + + // Check if the first byte of the buffer is accessible. + State = CheckLocation(C, State, Buffer, BufStart, Access, CK); + if (!State) + return nullptr; + // Get the access length and make sure it is known. // FIXME: This assumes the caller has already checked that the access length // is positive. And that it's unsigned. @@ -496,8 +504,6 @@ NonLoc LastOffset = Offset.castAs<NonLoc>(); // Check that the first buffer is sufficiently long. - SVal BufStart = - svalBuilder.evalCast(BufVal, PtrTy, Buffer.Expression->getType()); if (std::optional<Loc> BufLoc = BufStart.getAs<Loc>()) { SVal BufEnd =
Index: clang/test/Analysis/string.c =================================================================== --- clang/test/Analysis/string.c +++ clang/test/Analysis/string.c @@ -71,6 +71,7 @@ int scanf(const char *restrict format, ...); void *malloc(size_t); void free(void *); +void *memcpy(void *dest, const void *src, unsigned long n); //===----------------------------------------------------------------------=== // strlen() @@ -1713,3 +1714,21 @@ free(dataBuffer); } #endif + +#ifndef SUPPRESS_OUT_OF_BOUND +void CWE124_Buffer_Underwrite__malloc_char_memcpy() { + char * dataBuffer = (char *)malloc(100*sizeof(char)); + if (dataBuffer == NULL) return; + memset(dataBuffer, 'A', 100-1); + dataBuffer[100-1] = '\0'; + char *data = dataBuffer - 8; + + char source[100]; + memset(source, 'C', 100-1); // fill with 'C's + source[100-1] = '\0'; // null terminate + + memcpy(data, source, 100*sizeof(char)); // expected-warning {{Memory copy function overflows the destination buffer}} + data[100-1] = '\0'; + free(dataBuffer); +} +#endif Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -480,6 +480,14 @@ if (!Filter.CheckCStringOutOfBounds) return State; + SVal BufStart = + svalBuilder.evalCast(BufVal, PtrTy, Buffer.Expression->getType()); + + // Check if the first byte of the buffer is accessible. + State = CheckLocation(C, State, Buffer, BufStart, Access, CK); + if (!State) + return nullptr; + // Get the access length and make sure it is known. // FIXME: This assumes the caller has already checked that the access length // is positive. And that it's unsigned. @@ -496,8 +504,6 @@ NonLoc LastOffset = Offset.castAs<NonLoc>(); // Check that the first buffer is sufficiently long. - SVal BufStart = - svalBuilder.evalCast(BufVal, PtrTy, Buffer.Expression->getType()); if (std::optional<Loc> BufLoc = BufStart.getAs<Loc>()) { SVal BufEnd =
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits