aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
diff options
context:
space:
mode:
authorBalazs Benics <benicsbalazs@gmail.com>2023-09-11 14:19:33 +0200
committerBalazs Benics <benicsbalazs@gmail.com>2023-09-11 14:19:33 +0200
commitc3a87ddad62a6cc01acaccc76592bc6730c8ac3c (patch)
treea57f943bf623b3692aa2eb353ff6681760dbfd3e /clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
parent4b9259b9470480cbe140e49858c08fd62f67d7c6 (diff)
downloadllvm-c3a87ddad62a6cc01acaccc76592bc6730c8ac3c.zip
llvm-c3a87ddad62a6cc01acaccc76592bc6730c8ac3c.tar.gz
llvm-c3a87ddad62a6cc01acaccc76592bc6730c8ac3c.tar.bz2
[analyzer] CStringChecker should check the first byte of the destination of strcpy, strncpy
By not checking if the first byte of the destination of strcpy and strncpy is writable, we missed some reports in the Juliet benchmark. (Juliet CWE-124 Buffer Underwrite: strcpy, strncpy) https://discourse.llvm.org/t/patches-inspired-by-the-juliet-benchmark/73106 Differential Revision: https://reviews.llvm.org/D159108
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp10
1 files changed, 10 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 7d3aaac..66ed78e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -2009,6 +2009,11 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
SVal maxLastElement =
svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal, *maxLastNL, ptrTy);
+ // Check if the first byte of the destination is writable.
+ state = CheckLocation(C, state, Dst, DstVal, AccessKind::write);
+ if (!state)
+ return;
+ // Check if the last byte of the destination is writable.
state = CheckLocation(C, state, Dst, maxLastElement, AccessKind::write);
if (!state)
return;
@@ -2021,6 +2026,11 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// ...and we haven't checked the bound, we'll check the actual copy.
if (!boundWarning) {
+ // Check if the first byte of the destination is writable.
+ state = CheckLocation(C, state, Dst, DstVal, AccessKind::write);
+ if (!state)
+ return;
+ // Check if the last byte of the destination is writable.
state = CheckLocation(C, state, Dst, lastElement, AccessKind::write);
if (!state)
return;