Hi krememek, zaks.anna, jordan_rose,
Enable static analyzer to throw warnings when uninitialized source array of
known length is given as the argument to strcpy function, where dest size <
source size.
char x[3] = "abc";
char y[4];
strcpy(x,y); // emit buffer overflow warning
http://reviews.llvm.org/D6012
Files:
lib/StaticAnalyzer/Checkers/CStringChecker.cpp
test/Analysis/string.c
Index: test/Analysis/string.c
===================================================================
--- test/Analysis/string.c
+++ test/Analysis/string.c
@@ -303,6 +303,24 @@
strcpy(x, y); // no-warning
}
+void strcpy_src_uninit_overflow1() {
+ char x[3] = "abc";
+ char y[4];
+ strcpy(x,y); // expected-warning{{String copy function overflows destination buffer}}
+}
+
+void strcpy_src_uninit_overflow2() {
+ char x[3] = "abc";
+ char y[3];
+ strcpy(x,y); // no-warning
+}
+
+void strcpy_src_uninit_overflow3() {
+ char x[3] = "abc";
+ char y[2];
+ strcpy(x,y); // no-warning
+}
+
//===----------------------------------------------------------------------===
// stpcpy()
//===----------------------------------------------------------------------===
Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -39,6 +39,7 @@
BT_NotCString, BT_AdditionOverflow;
mutable const char *CurrentFunctionDescription;
+ static bool isSrcUninit;
public:
/// The filter is used to filter out the diagnostics which are not enabled by
@@ -195,6 +196,8 @@
NonLoc right) const;
};
+bool CStringChecker::isSrcUninit = 0;
+
} //end anonymous namespace
REGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal)
@@ -667,6 +670,12 @@
const SVal *Recorded = state->get<CStringLength>(MR);
if (Recorded)
return *Recorded;
+ else {
+ // set isSrcUninit, so that we will try to evaluate size of src for strcpy fn
+ // if we cannot calculate size in strcpy function
+ // we will use the symbolic value generated after this.
+ isSrcUninit = 1;
+ }
}
// Otherwise, get a new symbol and update the state.
@@ -1360,6 +1369,35 @@
QualType cmpTy = svalBuilder.getConditionType();
QualType sizeTy = svalBuilder.getContext().getSizeType();
+ // If we could not record proper string length, try to get the size of src buffer
+ if (isSrcUninit && !isAppending && !isBounded && !returnEnd) {
+ isSrcUninit = 0;
+ const MemRegion *R = srcVal.getAsRegion();
+ if (!R)
+ return;
+
+ const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+ SVal retsize = UnknownVal();
+ if (ER) {
+ assert(ER->getValueType() == C.getASTContext().CharTy &&
+ "Should only be called with char* ElementRegions");
+
+ // Get the size of the array.
+ const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
+ SVal Extent = svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
+ DefinedOrUnknownSVal strSize = cast<DefinedOrUnknownSVal>(Extent);
+ retsize = strSize;
+
+ NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
+ NonLoc *knownStrSize = cast<NonLoc>(&retsize);
+ retsize = (svalBuilder.evalBinOpNN(state, BO_Sub, *knownStrSize, One, sizeTy));
+
+ if (!(retsize.isUnknown()) && !(retsize.isUndef())) {
+ strLength = retsize;
+ }
+ }
+ }
+
// These two values allow checking two kinds of errors:
// - actual overflows caused by a source that doesn't fit in the destination
// - potential overflows caused by a bound that could exceed the destination
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits