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 isSrcGarbage; public: /// The filter is used to filter out the diagnostics which are not enabled by @@ -195,6 +196,8 @@ NonLoc right) const; }; +bool CStringChecker::isSrcGarbage = 0; + } //end anonymous namespace REGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal) @@ -667,6 +670,10 @@ const SVal *Recorded = state->get(MR); if (Recorded) return *Recorded; + else { + // set isSrcGarbage, so that we will try to evaluate size of src for strcpy fn + isSrcGarbage = 1; + } } // Otherwise, get a new symbol and update the state. @@ -1360,6 +1367,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 (isSrcGarbage && !isAppending && !isBounded && !returnEnd) { + isSrcGarbage = 0; + const MemRegion *R = srcVal.getAsRegion(); + if (!R) + return; + + const ElementRegion *ER = dyn_cast(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(ER->getSuperRegion()); + SVal Extent = svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); + DefinedOrUnknownSVal strSize = cast(Extent); + retsize = strSize; + + NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs(); + NonLoc *knownStrSize = cast(&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 Index: test/Analysis/string.c =================================================================== --- test/Analysis/string.c +++ test/Analysis/string.c @@ -303,6 +303,14 @@ strcpy(x, y); // no-warning } +extern void * memset(void *, int , unsigned long ); +void strcpy_src_garbage_overflow1() { + char x[4] = "abc"; + char y[5]; + memset(y,'a',5); + strcpy(x,y); // expected-warning{{String copy function overflows destination buffer}} +} + //===----------------------------------------------------------------------=== // stpcpy() //===----------------------------------------------------------------------===