clang: lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

22#include

23

24using namespace clang;

26

27namespace {

28

29

30class LocField final : public FieldNode {

31

32 const bool IsDereferenced;

33

34public:

35 LocField(const FieldRegion *FR, const bool IsDereferenced = true)

36 : FieldNode(FR), IsDereferenced(IsDereferenced) {}

37

38 void printNoteMsg(llvm::raw_ostream &Out) const override {

39 if (IsDereferenced)

40 Out << "uninitialized pointee ";

41 else

42 Out << "uninitialized pointer ";

43 }

44

45 void printPrefix(llvm::raw_ostream &Out) const override {}

46

47 void printNode(llvm::raw_ostream &Out) const override {

49 }

50

51 void printSeparator(llvm::raw_ostream &Out) const override {

52 if (getDecl()->getType()->isPointerType())

53 Out << "->";

54 else

55 Out << '.';

56 }

57};

58

59

60

61class NeedsCastLocField final : public FieldNode {

63

64public:

67

68 void printNoteMsg(llvm::raw_ostream &Out) const override {

69 Out << "uninitialized pointee ";

70 }

71

72 void printPrefix(llvm::raw_ostream &Out) const override {

73

74 if (getDecl()->getType()->isIntegerType())

75 Out << "reinterpret_cast";

76

77 else

78 Out << "static_cast";

79 Out << '<' << CastBackType.getAsString() << ">(";

80 }

81

82 void printNode(llvm::raw_ostream &Out) const override {

84 }

85

86 void printSeparator(llvm::raw_ostream &Out) const override { Out << "->"; }

87};

88

89

90class CyclicLocField final : public FieldNode {

91

92public:

94

95 void printNoteMsg(llvm::raw_ostream &Out) const override {

96 Out << "object references itself ";

97 }

98

99 void printPrefix(llvm::raw_ostream &Out) const override {}

100

101 void printNode(llvm::raw_ostream &Out) const override {

103 }

104

105 void printSeparator(llvm::raw_ostream &Out) const override {

106 llvm_unreachable("CyclicLocField objects must be the last node of the "

107 "fieldchain!");

108 }

109};

110

111}

112

113

114

121};

122

123

124

125

128

129

130

132

133

134

135

136

137bool FindUninitializedFields::isDereferencableUninit(

139

140 SVal V = State->getSVal(FR);

141

143 isanonloc::LocAsInteger(V)) &&

144 "This method only checks dereferenceable objects!");

145

146 if (V.isUnknown() || isaloc::ConcreteInt(V)) {

147 IsAnyFieldInitialized = true;

148 return false;

149 }

150

151 if (V.isUndef()) {

152 return addFieldToUninits(

153 LocalChain.add(LocField(FR, false)), FR);

154 }

155

157 IsAnyFieldInitialized = true;

158 return false;

159 }

160

161

162

163 std::optional DerefInfo = dereference(State, FR);

164 if (!DerefInfo) {

165 IsAnyFieldInitialized = true;

166 return false;

167 }

168

169 if (DerefInfo->IsCyclic)

170 return addFieldToUninits(LocalChain.add(CyclicLocField(FR)), FR);

171

173 const bool NeedsCastBack = DerefInfo->NeedsCastBack;

174

177

179 if (NeedsCastBack)

180 return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT)));

181 return isNonUnionUninit(R, LocalChain.add(LocField(FR)));

182 }

183

185 if (isUnionUninit(R)) {

186 if (NeedsCastBack)

187 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)),

188 R);

189 return addFieldToUninits(LocalChain.add(LocField(FR)), R);

190 } else {

191 IsAnyFieldInitialized = true;

192 return false;

193 }

194 }

195

197 IsAnyFieldInitialized = true;

198 return false;

199 }

200

202 "At this point FR must either have a primitive dynamic type, or it "

203 "must be a null, undefined, unknown or concrete pointer!");

204

205 SVal PointeeV = State->getSVal(R);

206

207 if (isPrimitiveUninit(PointeeV)) {

208 if (NeedsCastBack)

209 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)), R);

210 return addFieldToUninits(LocalChain.add(LocField(FR)), R);

211 }

212

213 IsAnyFieldInitialized = true;

214 return false;

215}

216

217

218

219

220

223

224 llvm::SmallSet<const TypedValueRegion *, 5> VisitedRegions;

225

226 SVal V = State->getSVal(FR);

227 assert(V.getAsRegion() && "V must have an underlying region!");

228

229

230

231

232 bool NeedsCastBack =

234

235

237 if (!R)

238 return std::nullopt;

239

240 VisitedRegions.insert(R);

241

242

244

245 while (const MemRegion *Tmp = State->getSVal(R, DynT).getAsRegion()) {

246

248 if (!R)

249 return std::nullopt;

250

251

252 if (!VisitedRegions.insert(R).second)

253 return DereferenceInfo{R, NeedsCastBack, true};

254

256

257

259 break;

260 }

261

262 while (isa(R)) {

263 NeedsCastBack = true;

264 const auto *SuperR = dyn_cast(R->getSuperRegion());

265 if (!SuperR)

266 break;

267

268 R = SuperR;

269 }

270

271 return DereferenceInfo{R, NeedsCastBack, false};

272}

273

275 while (T.isNull()) {

277 return true;

279 }

280 return false;

281}

static std::optional< DereferenceInfo > dereference(ProgramStateRef State, const FieldRegion *FR)

Dereferences FR and returns with the pointee's region, and whether it needs to be casted back to it's...

static bool isVoidPointer(QualType T)

Returns whether T can be (transitively) dereferenced to a void pointer type (void*,...

A (possibly-)qualified type.

bool isVoidPointerType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isStructureOrClassType() const

Represents a field chain.

FieldChainInfo add(const FieldNodeT &FN)

Constructs a new FieldChainInfo object with FN appended.

A lightweight polymorphic wrapper around FieldRegion *.

virtual void printSeparator(llvm::raw_ostream &Out) const =0

Print the separator.

virtual void printPrefix(llvm::raw_ostream &Out) const =0

Print any prefixes before the fieldchain. Could contain casts, etc.

virtual void printNoteMsg(llvm::raw_ostream &Out) const =0

If this is the last element of the fieldchain, this method will print the note message associated wit...

const FieldDecl * getDecl() const

virtual void printNode(llvm::raw_ostream &Out) const =0

Print the node. Should contain the name of the field stored in FR.

LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override

MemRegion - The root abstract class for all memory regions.

const RegionTy * getAs() const

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const

TypedValueRegion - An abstract class representing regions having a typed value.

QualType getLocationType() const override

std::string getVariableName(const FieldDecl *Field)

Returns with Field's name.

bool isPrimitiveType(const QualType &T)

Returns true if T is a primitive type.

bool isDereferencableType(const QualType &T)

The JSON file list parser is used to communicate input to InstallAPI.

const FunctionProtoType * T

DereferenceInfo(const TypedValueRegion *R, bool NCB, bool IC)

const TypedValueRegion * R

bool CheckPointeeInitialization