@@ -179,59 +179,6 @@ static void describeUninitializedArgumentInCall(const CallEvent &Call,
179179 }
180180}
181181
182- bool CallAndMessageChecker::uninitRefOrPointer (
183- CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx,
184- const BugType &BT, const ParmVarDecl *ParamDecl, int ArgumentNumber) const {
185-
186- if (!ChecksEnabled[CK_ArgPointeeInitializedness])
187- return false ;
188-
189- // No parameter declaration available, i.e. variadic function argument.
190- if (!ParamDecl)
191- return false ;
192-
193- // If parameter is declared as pointer to const in function declaration,
194- // then check if corresponding argument in function call is
195- // pointing to undefined symbol value (uninitialized memory).
196- SmallString<200 > Buf;
197- llvm::raw_svector_ostream Os (Buf);
198-
199- if (ParamDecl->getType ()->isPointerType ()) {
200- Os << (ArgumentNumber + 1 ) << llvm::getOrdinalSuffix (ArgumentNumber + 1 )
201- << " function call argument is a pointer to uninitialized value" ;
202- } else if (ParamDecl->getType ()->isReferenceType ()) {
203- Os << (ArgumentNumber + 1 ) << llvm::getOrdinalSuffix (ArgumentNumber + 1 )
204- << " function call argument is an uninitialized value" ;
205- } else
206- return false ;
207-
208- if (!ParamDecl->getType ()->getPointeeType ().isConstQualified ())
209- return false ;
210-
211- if (const MemRegion *SValMemRegion = V.getAsRegion ()) {
212- const ProgramStateRef State = C.getState ();
213- QualType T = ParamDecl->getType ()->getPointeeType ();
214- if (T->isVoidType ())
215- T = C.getASTContext ().CharTy ;
216- const SVal PSV = State->getSVal (SValMemRegion, T);
217- bool IsUndef = PSV.isUndef ();
218- if (auto LCV = PSV.getAs <nonloc::LazyCompoundVal>())
219- IsUndef = LCV->getStore () == nullptr ;
220- if (IsUndef) {
221- if (ExplodedNode *N = C.generateErrorNode ()) {
222- auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str (), N);
223- R->addRange (ArgRange);
224- if (ArgEx)
225- bugreporter::trackExpressionValue (N, ArgEx, *R);
226-
227- C.emitReport (std::move (R));
228- }
229- return true ;
230- }
231- }
232- return false ;
233- }
234-
235182namespace {
236183class FindUninitializedField {
237184public:
@@ -272,9 +219,115 @@ class FindUninitializedField {
272219
273220 return false ;
274221 }
222+
223+ void printFieldChain (llvm::raw_ostream &OS) {
224+ if (FieldChain.size () == 1 )
225+ OS << " (e.g., field: '" << *FieldChain[0 ] << " ')" ;
226+ else {
227+ OS << " (e.g., via the field chain: '" ;
228+ bool First = true ;
229+ for (SmallVectorImpl<const FieldDecl *>::iterator DI = FieldChain.begin (),
230+ DE = FieldChain.end ();
231+ DI != DE; ++DI) {
232+ if (First)
233+ First = false ;
234+ else
235+ OS << ' .' ;
236+ OS << **DI;
237+ }
238+ OS << " ')" ;
239+ }
240+ }
275241};
276242} // namespace
277243
244+ bool CallAndMessageChecker::uninitRefOrPointer (
245+ CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx,
246+ const BugType &BT, const ParmVarDecl *ParamDecl, int ArgumentNumber) const {
247+
248+ if (!ChecksEnabled[CK_ArgPointeeInitializedness])
249+ return false ;
250+
251+ // No parameter declaration available, i.e. variadic function argument.
252+ if (!ParamDecl)
253+ return false ;
254+
255+ QualType ParamT = ParamDecl->getType ();
256+ if (!ParamT->isPointerOrReferenceType ())
257+ return false ;
258+
259+ QualType PointeeT = ParamT->getPointeeType ();
260+ if (!PointeeT.isConstQualified ())
261+ return false ;
262+
263+ const MemRegion *SValMemRegion = V.getAsRegion ();
264+ if (!SValMemRegion)
265+ return false ;
266+
267+ // If parameter is declared as pointer to const in function declaration,
268+ // then check if corresponding argument in function call is
269+ // pointing to undefined symbol value (uninitialized memory).
270+
271+ const ProgramStateRef State = C.getState ();
272+ if (PointeeT->isVoidType ())
273+ PointeeT = C.getASTContext ().CharTy ;
274+ const SVal PointeeV =
275+ State->getSVal (SValMemRegion, PointeeT);
276+
277+ if (PointeeV.isUndef ()) {
278+ if (ExplodedNode *N = C.generateErrorNode ()) {
279+ SmallString<200 > Buf;
280+ llvm::raw_svector_ostream Os (Buf);
281+ Os << (ArgumentNumber + 1 ) << llvm::getOrdinalSuffix (ArgumentNumber + 1 )
282+ << " function call argument is " ;
283+ if (ParamT->isPointerType ())
284+ Os << " a pointer to uninitialized value" ;
285+ else
286+ Os << " an uninitialized value" ;
287+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str (), N);
288+ R->addRange (ArgRange);
289+ if (ArgEx)
290+ bugreporter::trackExpressionValue (N, ArgEx, *R);
291+
292+ C.emitReport (std::move (R));
293+ }
294+ return true ;
295+ }
296+
297+ if (auto LV = PointeeV.getAs <nonloc::LazyCompoundVal>()) {
298+ const LazyCompoundValData *D = LV->getCVData ();
299+ FindUninitializedField F (C.getState ()->getStateManager ().getStoreManager (),
300+ C.getSValBuilder ().getRegionManager (),
301+ D->getStore ());
302+
303+ if (F.Find (D->getRegion ())) {
304+ if (ExplodedNode *N = C.generateErrorNode ()) {
305+ SmallString<512 > Buf;
306+ llvm::raw_svector_ostream Os (Buf);
307+ Os << (ArgumentNumber + 1 ) << llvm::getOrdinalSuffix (ArgumentNumber + 1 )
308+ << " function call argument" ;
309+ if (ParamT->isPointerType ())
310+ Os << " points to" ;
311+ else
312+ Os << " references" ;
313+ Os << " an uninitialized value" ;
314+
315+ F.printFieldChain (Os);
316+
317+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str (), N);
318+ R->addRange (ArgRange);
319+
320+ if (ArgEx)
321+ bugreporter::trackExpressionValue (N, ArgEx, *R);
322+ C.emitReport (std::move (R));
323+ }
324+ return true ;
325+ }
326+ }
327+
328+ return false ;
329+ }
330+
278331bool CallAndMessageChecker::PreVisitProcessArg (
279332 CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx,
280333 int ArgumentNumber, bool CheckUninitFields, const CallEvent &Call,
@@ -320,22 +373,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(
320373 SmallString<512 > Str;
321374 llvm::raw_svector_ostream os (Str);
322375 os << " Passed-by-value struct argument contains uninitialized data" ;
323-
324- if (F.FieldChain .size () == 1 )
325- os << " (e.g., field: '" << *F.FieldChain [0 ] << " ')" ;
326- else {
327- os << " (e.g., via the field chain: '" ;
328- bool first = true ;
329- for (SmallVectorImpl<const FieldDecl *>::iterator
330- DI = F.FieldChain .begin (), DE = F.FieldChain .end (); DI!=DE;++DI){
331- if (first)
332- first = false ;
333- else
334- os << ' .' ;
335- os << **DI;
336- }
337- os << " ')" ;
338- }
376+ F.printFieldChain (os);
339377
340378 // Generate a report for this bug.
341379 auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str (), N);
0 commit comments