A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://clang.llvm.org/doxygen/CStringChecker_8cpp_source.html below:

clang: lib/StaticAnalyzer/Checkers/CStringChecker.cpp Source File

30#include "llvm/ADT/APSInt.h" 31#include "llvm/ADT/STLExtras.h" 32#include "llvm/ADT/StringExtras.h" 33#include "llvm/Support/Casting.h" 34#include "llvm/Support/raw_ostream.h" 38using namespace clang

;

40using namespace

std::placeholders;

45 unsigned

ArgumentIndex;

47struct

SourceArgExpr : AnyArgExpr {};

48struct

DestinationArgExpr : AnyArgExpr {};

49struct

SizeArgExpr : AnyArgExpr {};

52enum class

AccessKind { write, read };

54static

ErrorMessage createOutOfBoundErrorMsg(StringRef FunctionDescription,

57

llvm::raw_svector_ostream Os(Message);

61

<< &FunctionDescription.data()[1];

63 if

(Access == AccessKind::write) {

64

Os <<

" overflows the destination buffer"

;

66

Os <<

" accesses out-of-bound array element"

;

72enum class

ConcatFnKind { none = 0, strcat = 1, strlcat = 2 };

74enum class

CharKind { Regular = 0,

Wide

};

75constexpr

CharKind CK_Regular = CharKind::Regular;

76constexpr

CharKind CK_Wide = CharKind::Wide;

83class

CStringChecker :

public Checker

< eval::Call,

84

check::PreStmt<DeclStmt>,

89 mutable

std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap,

90

BT_NotCString, BT_AdditionOverflow, BT_UninitRead;

92 mutable const char

*CurrentFunctionDescription =

nullptr

;

97 struct

CStringChecksFilter {

98 bool

CheckCStringNullArg =

false

;

99 bool

CheckCStringOutOfBounds =

false

;

100 bool

CheckCStringBufferOverlap =

false

;

101 bool

CheckCStringNotNullTerm =

false

;

102 bool

CheckCStringUninitializedRead =

false

;

111

CStringChecksFilter

Filter

;

113 static void

*getTag() {

static int

tag;

return

&tag; }

128 using

FnCheck = std::function<void(

const

CStringChecker *,

CheckerContext

&,

132

{{CDM::CLibraryMaybeHardened, {

"memcpy"

}, 3},

133

std::bind(&CStringChecker::evalMemcpy, _1,

_2

, _3, CK_Regular)},

134

{{CDM::CLibraryMaybeHardened, {

"wmemcpy"

}, 3},

135

std::bind(&CStringChecker::evalMemcpy, _1,

_2

, _3, CK_Wide)},

136

{{CDM::CLibraryMaybeHardened, {

"mempcpy"

}, 3},

137

std::bind(&CStringChecker::evalMempcpy, _1,

_2

, _3, CK_Regular)},

138

{{CDM::CLibraryMaybeHardened, {

"wmempcpy"

}, 3},

139

std::bind(&CStringChecker::evalMempcpy, _1,

_2

, _3, CK_Wide)},

140

{{CDM::CLibrary, {

"memcmp"

}, 3},

141

std::bind(&CStringChecker::evalMemcmp, _1,

_2

, _3, CK_Regular)},

142

{{CDM::CLibrary, {

"wmemcmp"

}, 3},

143

std::bind(&CStringChecker::evalMemcmp, _1,

_2

, _3, CK_Wide)},

144

{{CDM::CLibraryMaybeHardened, {

"memmove"

}, 3},

145

std::bind(&CStringChecker::evalMemmove, _1,

_2

, _3, CK_Regular)},

146

{{CDM::CLibraryMaybeHardened, {

"wmemmove"

}, 3},

147

std::bind(&CStringChecker::evalMemmove, _1,

_2

, _3, CK_Wide)},

148

{{CDM::CLibraryMaybeHardened, {

"memset"

}, 3},

149

&CStringChecker::evalMemset},

150

{{CDM::CLibrary, {

"explicit_memset"

}, 3}, &CStringChecker::evalMemset},

152

{{CDM::CLibraryMaybeHardened, {

"strcpy"

}, 2},

153

&CStringChecker::evalStrcpy},

154

{{CDM::CLibraryMaybeHardened, {

"strncpy"

}, 3},

155

&CStringChecker::evalStrncpy},

156

{{CDM::CLibraryMaybeHardened, {

"stpcpy"

}, 2},

157

&CStringChecker::evalStpcpy},

158

{{CDM::CLibraryMaybeHardened, {

"strlcpy"

}, 3},

159

&CStringChecker::evalStrlcpy},

160

{{CDM::CLibraryMaybeHardened, {

"strcat"

}, 2},

161

&CStringChecker::evalStrcat},

162

{{CDM::CLibraryMaybeHardened, {

"strncat"

}, 3},

163

&CStringChecker::evalStrncat},

164

{{CDM::CLibraryMaybeHardened, {

"strlcat"

}, 3},

165

&CStringChecker::evalStrlcat},

166

{{CDM::CLibraryMaybeHardened, {

"strlen"

}, 1},

167

&CStringChecker::evalstrLength},

168

{{CDM::CLibrary, {

"wcslen"

}, 1}, &CStringChecker::evalstrLength},

169

{{CDM::CLibraryMaybeHardened, {

"strnlen"

}, 2},

170

&CStringChecker::evalstrnLength},

171

{{CDM::CLibrary, {

"wcsnlen"

}, 2}, &CStringChecker::evalstrnLength},

172

{{CDM::CLibrary, {

"strcmp"

}, 2}, &CStringChecker::evalStrcmp},

173

{{CDM::CLibrary, {

"strncmp"

}, 3}, &CStringChecker::evalStrncmp},

174

{{CDM::CLibrary, {

"strcasecmp"

}, 2}, &CStringChecker::evalStrcasecmp},

175

{{CDM::CLibrary, {

"strncasecmp"

}, 3}, &CStringChecker::evalStrncasecmp},

176

{{CDM::CLibrary, {

"strsep"

}, 2}, &CStringChecker::evalStrsep},

177

{{CDM::CLibrary, {

"bcopy"

}, 3}, &CStringChecker::evalBcopy},

178

{{CDM::CLibrary, {

"bcmp"

}, 3},

179

std::bind(&CStringChecker::evalMemcmp, _1,

_2

, _3, CK_Regular)},

180

{{CDM::CLibrary, {

"bzero"

}, 2}, &CStringChecker::evalBzero},

181

{{CDM::CLibraryMaybeHardened, {

"explicit_bzero"

}, 2},

182

&CStringChecker::evalBzero},

190

{{CDM::CLibraryMaybeHardened, {

"sprintf"

}, std::nullopt, 2},

191

&CStringChecker::evalSprintf},

192

{{CDM::CLibraryMaybeHardened, {

"snprintf"

}, std::nullopt, 3},

193

&CStringChecker::evalSnprintf},

198

StdCopyBackward{CDM::SimpleFunc, {

"std"

,

"copy_backward"

}, 3};

207

DestinationArgExpr Dest, SourceArgExpr Source,

208 bool

Restricted,

bool

IsMempcpy, CharKind CK)

const

;

215 bool

IsStrnlen =

false

)

const

;

222 bool

ReturnEnd,

bool

IsBounded, ConcatFnKind appendK,

223 bool

returnPtr =

true

)

const

;

234 bool

IsBounded =

false

,

bool

IgnoreCase =

false

)

const

;

247 bool

IsBounded)

const

;

250

std::pair<ProgramStateRef , ProgramStateRef >

266 bool

hypothetical =

false

)

const

;

285 static ProgramStateRef

invalidateDestinationBufferAlwaysEscapeSuperRegion(

300

InvalidationTraitOperations);

302 static bool

SummarizeRegion(raw_ostream &os,

ASTContext

&Ctx,

305 static bool

memsetAux(

const Expr

*DstBuffer,

SVal

CharE,

311

AnyArgExpr Arg,

SVal

l)

const

;

315

AnyArgExpr Buffer,

SVal

Element,

SVal

Size)

const

;

317

AnyArgExpr Buffer,

SVal

Element,

319

CharKind CK = CharKind::Regular)

const

;

321

AnyArgExpr Buffer, SizeArgExpr Size,

323

CharKind CK = CharKind::Regular)

const

;

325

SizeArgExpr Size, AnyArgExpr

First

,

327

CharKind CK = CharKind::Regular)

const

;

331 const Stmt

*Second)

const

;

334

StringRef WarningMsg)

const

;

336 const Stmt

*S, StringRef WarningMsg)

const

;

338 const Stmt

*S, StringRef WarningMsg)

const

;

342

StringRef Msg)

const

;

364

std::pair<ProgramStateRef, ProgramStateRef>

367

std::optional<DefinedSVal> val =

V

.getAs<

DefinedSVal

>();

369 return

std::pair<ProgramStateRef, ProgramStateRef>(State, State);

373 return

State->assume(svalBuilder.

evalEQ

(State, *val, zero));

378

AnyArgExpr Arg,

SVal

l)

const

{

384

std::tie(stateNull, stateNonNull) =

385

assumeZero(

C

, State, l, Arg.Expression->getType());

387 if

(stateNull && !stateNonNull) {

388 if

(

Filter

.CheckCStringNullArg) {

390

llvm::raw_svector_ostream OS(buf);

391

assert(CurrentFunctionDescription);

392

OS <<

"Null pointer passed as "

<< (Arg.ArgumentIndex + 1)

393

<< llvm::getOrdinalSuffix(Arg.ArgumentIndex + 1) <<

" argument to " 394

<< CurrentFunctionDescription;

396

emitNullArgBug(

C

, stateNull, Arg.Expression, OS.str());

402

assert(stateNonNull);

408 SValBuilder

&SVB = State->getStateManager().getSValBuilder();

411 if

(CK == CharKind::Regular) {

427 if

(Offset.isUnknown())

429 return

Offset.castAs<

NonLoc

>();

434

Os << Idx << llvm::getOrdinalSuffix(Idx);

439

AnyArgExpr Buffer,

SVal

Element,

446 const MemRegion

*R = Element.getAsRegion();

447 const auto

*ER = dyn_cast_or_null<ElementRegion>(R);

457 if

(!SuperR->getValueType()->isArrayType())

466

std::optional<Loc> FirstElementVal =

468 if

(!FirstElementVal)

472 if

(

Filter

.CheckCStringUninitializedRead &&

473

State->getSVal(*FirstElementVal).isUndef()) {

475

llvm::raw_svector_ostream OS(Buf);

476

OS <<

"The first element of the "

;

478

OS <<

" argument is undefined"

;

479

emitUninitializedReadBug(

C

, State, Buffer.Expression,

480

FirstElementVal->getAsRegion(), OS.str());

511

std::optional<NonLoc> Offset =

523 SVal

LastElementVal =

525 if

(!isa<Loc>(LastElementVal))

528 if

(

Filter

.CheckCStringUninitializedRead &&

529

State->getSVal(LastElementVal.

castAs

<

Loc

>()).isUndef()) {

530 const

llvm::APSInt *IdxInt = LastIdx.getAsInteger();

538

llvm::raw_svector_ostream OS(Buf);

539

OS <<

"The last accessed element (at index "

;

540

OS << IdxInt->getExtValue();

543

OS <<

" argument is undefined"

;

544

emitUninitializedReadBug(

C

, State, Buffer.Expression,

554

AnyArgExpr Buffer,

SVal

Element,

563 const MemRegion

*R = Element.getAsRegion();

567 const auto

*ER = dyn_cast<ElementRegion>(R);

572

std::optional<NonLoc> Idx =

getIndex

(state, ER, CK);

577 const auto

*superReg = cast<SubRegion>(ER->getSuperRegion());

581 auto

[StInBound, StOutBound] = state->assumeInBoundDual(*Idx, Size);

582 if

(StOutBound && !StInBound) {

586 if

(!

Filter

.CheckCStringOutOfBounds)

590

ErrorMessage Message =

591

createOutOfBoundErrorMsg(CurrentFunctionDescription, Access);

592

emitOutOfBoundsBug(

C

, StOutBound, Buffer.Expression, Message);

603

AnyArgExpr Buffer, SizeArgExpr Size,

604

AccessKind Access, CharKind CK)

const

{

613 QualType

PtrTy = getCharPtrType(Ctx, CK);

616 SVal

BufVal =

C

.getSVal(Buffer.Expression);

617

State = checkNonNull(

C

, State, Buffer, BufVal);

622 if

(!

Filter

.CheckCStringOutOfBounds)

626

svalBuilder.

evalCast

(BufVal, PtrTy, Buffer.Expression->getType());

629

State = CheckLocation(

C

, State, Buffer, BufStart, Access, CK);

637 SVal

LengthVal =

C

.getSVal(

Size

.Expression);

638

std::optional<NonLoc> Length = LengthVal.

getAs

<

NonLoc

>();

644 SVal

Offset = svalBuilder.

evalBinOpNN

(State, BO_Sub, *Length, One, SizeTy);

645 if

(Offset.isUnknown())

650 if

(std::optional<Loc> BufLoc = BufStart.

getAs

<

Loc

>()) {

653

svalBuilder.

evalBinOpLN

(State, BO_Add, *BufLoc, LastOffset, PtrTy);

654

State = CheckLocation(

C

, State, Buffer, BufEnd, Access, CK);

655 if

(Access == AccessKind::read)

656

State = checkInit(

C

, State, Buffer, BufEnd, *Length);

669

SizeArgExpr Size, AnyArgExpr

First

,

672 if

(!

Filter

.CheckCStringBufferOverlap)

686 if

(

First

.Expression->getType()->getPointeeType().getAddressSpace() !=

687

Second.Expression->getType()->getPointeeType().getAddressSpace())

692 SVal

firstVal = state->getSVal(

First

.Expression, LCtx);

693 SVal

secondVal = state->getSVal(Second.Expression, LCtx);

695

std::optional<Loc> firstLoc = firstVal.

getAs

<

Loc

>();

699

std::optional<Loc> secondLoc = secondVal.

getAs

<

Loc

>();

705

std::tie(stateTrue, stateFalse) =

706

state->assume(svalBuilder.

evalEQ

(state, *firstLoc, *secondLoc));

708 if

(stateTrue && !stateFalse) {

710

emitOverlapBug(

C

, stateTrue,

First

.Expression, Second.Expression);

721

svalBuilder.

evalBinOpLL

(state, BO_GT, *firstLoc, *secondLoc, cmpTy);

722

std::optional<DefinedOrUnknownSVal> reverseTest =

727

std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);

734

std::swap(firstLoc, secondLoc);

737

std::swap(

First

, Second);

742 SVal

LengthVal = state->getSVal(

Size

.Expression, LCtx);

743

std::optional<NonLoc> Length = LengthVal.

getAs

<

NonLoc

>();

750 QualType

CharPtrTy = getCharPtrType(Ctx, CK);

752

svalBuilder.

evalCast

(*firstLoc, CharPtrTy,

First

.Expression->getType());

753

std::optional<Loc> FirstStartLoc = FirstStart.

getAs

<

Loc

>();

758 SVal

FirstEnd = svalBuilder.

evalBinOpLN

(state, BO_Add, *FirstStartLoc,

760

std::optional<Loc> FirstEndLoc = FirstEnd.

getAs

<

Loc

>();

766

svalBuilder.

evalBinOpLL

(state, BO_GT, *FirstEndLoc, *secondLoc, cmpTy);

767

std::optional<DefinedOrUnknownSVal> OverlapTest =

772

std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);

774 if

(stateTrue && !stateFalse) {

776

emitOverlapBug(

C

, stateTrue,

First

.Expression, Second.Expression);

792

BT_Overlap.reset(

new BugType

(

Filter

.CheckNameCStringBufferOverlap,

796 auto

report = std::make_unique<PathSensitiveBugReport>(

797

*BT_Overlap,

"Arguments must not be overlapping buffers"

, N);

798

report->addRange(

First

->getSourceRange());

801 C

.emitReport(std::move(report));

805 const Stmt

*S, StringRef WarningMsg)

const

{

815

std::make_unique<PathSensitiveBugReport>(*BT_Null, WarningMsg, N);

816 Report

->addRange(S->getSourceRange());

817 if

(

const auto

*Ex = dyn_cast<Expr>(S))

819 C

.emitReport(std::move(

Report

));

826

StringRef Msg)

const

{

829

BT_UninitRead.reset(

new BugType

(

Filter

.CheckNameCStringUninitializedRead,

830 "Accessing unitialized/garbage values"

));

833

std::make_unique<PathSensitiveBugReport>(*BT_UninitRead, Msg, N);

834 Report

->addNote(

"Other elements might also be undefined"

,

839 C

.emitReport(std::move(

Report

));

845

StringRef WarningMsg)

const

{

848

BT_Bounds.reset(

new BugType

(

Filter

.CheckCStringOutOfBounds

849

?

Filter

.CheckNameCStringOutOfBounds

850

:

Filter

.CheckNameCStringNullArg,

851 "Out-of-bound array access"

));

857

std::make_unique<PathSensitiveBugReport>(*BT_Bounds, WarningMsg, N);

858 Report

->addRange(S->getSourceRange());

859 C

.emitReport(std::move(

Report

));

865

StringRef WarningMsg)

const

{

866 if

(

ExplodedNode

*N =

C

.generateNonFatalErrorNode(State)) {

867 if

(!BT_NotCString) {

875

std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N);

877 Report

->addRange(S->getSourceRange());

878 C

.emitReport(std::move(

Report

));

885 if

(!BT_AdditionOverflow) {

889

BT_AdditionOverflow.reset(

896 const char

*WarningMsg =

897 "This expression will create a string whose length is too big to " 898 "be represented as a size_t"

;

900 auto Report

= std::make_unique<PathSensitiveBugReport>(*BT_AdditionOverflow,

902 C

.emitReport(std::move(

Report

));

911 if

(!

Filter

.CheckCStringOutOfBounds)

922 const

llvm::APSInt &maxValInt = BVF.

getMaxValue

(sizeTy);

926 if

(isa<nonloc::ConcreteInt>(right)) {

927

maxMinusRight = svalBuilder.

evalBinOpNN

(state, BO_Sub, maxVal, right,

932

maxMinusRight = svalBuilder.

evalBinOpNN

(state, BO_Sub, maxVal, left,

937 if

(std::optional<NonLoc> maxMinusRightNL = maxMinusRight.

getAs

<

NonLoc

>()) {

941

*maxMinusRightNL, cmpTy);

944

std::tie(stateOverflow, stateOkay) =

947 if

(stateOverflow && !stateOkay) {

949

emitAdditionOverflowBug(

C

, stateOverflow);

964

assert(!strLength.

isUndef

() &&

"Attempt to set an undefined string length"

);

969 case

MemRegion::StringRegionKind:

974 case

MemRegion::SymbolicRegionKind:

975 case

MemRegion::AllocaRegionKind:

976 case

MemRegion::NonParamVarRegionKind:

977 case

MemRegion::ParamVarRegionKind:

978 case

MemRegion::FieldRegionKind:

979 case

MemRegion::ObjCIvarRegionKind:

983 case

MemRegion::ElementRegionKind:

997 return

state->remove<CStringLength>(MR);

999 return

state->set<CStringLength>(MR, strLength);

1006 bool

hypothetical) {

1007 if

(!hypothetical) {

1009 const SVal

*Recorded = state->get<CStringLength>(MR);

1019 C

.getLocationContext(),

1022 if

(!hypothetical) {

1023 if

(std::optional<NonLoc> strLn = strLength.

getAs

<

NonLoc

>()) {

1026 const

llvm::APSInt &maxValInt = BVF.

getMaxValue

(sizeTy);

1028

std::optional<APSIntPtr> maxLengthInt =

1029

BVF.

evalAPSInt

(BO_Div, maxValInt, fourInt);

1031 SVal

evalLength = svalBuilder.

evalBinOpNN

(state, BO_LE, *strLn, maxLength,

1035

state = state->set<CStringLength>(MR, strLength);

1043 bool

hypothetical)

const

{

1050 if

(

Filter

.CheckCStringNotNullTerm) {

1052

llvm::raw_svector_ostream os(buf);

1053

assert(CurrentFunctionDescription);

1054

os <<

"Argument to "

<< CurrentFunctionDescription

1055

<<

" is the address of the label '"

<<

Label

->getLabel()->getName()

1056

<<

"', which is not a null-terminated string"

;

1058

emitNotCStringBug(

C

, state, Ex, os.str());

1072 case

MemRegion::StringRegionKind: {

1077 const StringLiteral

*strLit = cast<StringRegion>(MR)->getStringLiteral();

1080 case

MemRegion::NonParamVarRegionKind: {

1083 const VarDecl

*

Decl

= cast<NonParamVarRegion>(MR)->getDecl();

1084 if

(

Decl

->getType().isConstQualified() &&

Decl

->hasGlobalStorage()) {

1086 if

(

auto

*StrLit = dyn_cast<StringLiteral>(

Init

)) {

1089 return

SvalBuilder.

makeIntVal

(StrLit->getLength(), SizeTy);

1095 case

MemRegion::SymbolicRegionKind:

1096 case

MemRegion::AllocaRegionKind:

1097 case

MemRegion::ParamVarRegionKind:

1098 case

MemRegion::FieldRegionKind:

1099 case

MemRegion::ObjCIvarRegionKind:

1100 return

getCStringLengthForRegion(

C

, state, Ex, MR, hypothetical);

1101 case

MemRegion::CompoundLiteralRegionKind:

1104 case

MemRegion::ElementRegionKind:

1112 if

(

Filter

.CheckCStringNotNullTerm) {

1114

llvm::raw_svector_ostream os(buf);

1116

assert(CurrentFunctionDescription);

1117

os <<

"Argument to "

<< CurrentFunctionDescription <<

" is "

;

1119 if

(SummarizeRegion(os,

C

.getASTContext(), MR))

1120

os <<

", which is not a null-terminated string"

;

1122

os <<

"not a null-terminated string"

;

1124

emitNotCStringBug(

C

, state, Ex, os.str());

1142 const StringRegion

*strRegion= dyn_cast<StringRegion>(bufRegion);

1166

std::optional<NonLoc> Length = LengthVal.

getAs

<

NonLoc

>();

1172 SVal

Offset = SB.

evalBinOpNN

(State, BO_Sub, *Length, One, LengthTy);

1173 if

(Offset.isUnknown())

1179

std::optional<Loc> BufLoc = BufStart.

getAs

<

Loc

>();

1183 SVal

BufEnd = SB.

evalBinOpLN

(State, BO_Add, *BufLoc, LastOffset, PtrTy);

1197 "isFirstBufInBound should only be called with char* ElementRegions"

);

1208 return static_cast<bool>

(StInBound);

1214 auto

InvalidationTraitOperations =

1215

[&

C

, S, BufTy = BufE->

getType

(), BufV, SizeV,

1219 if

(MemRegion::FieldRegionKind == R->

getKind

() &&

1220

isFirstBufInBound(

C

, S, BufV, BufTy, SizeV, SizeTy)) {

1228 return

invalidateBufferAux(

C

, S, BufE, BufV, InvalidationTraitOperations);

1232

CStringChecker::invalidateDestinationBufferAlwaysEscapeSuperRegion(

1236 return

isa<FieldRegion>(R);

1239 return

invalidateBufferAux(

C

, S, BufE, BufV, InvalidationTraitOperations);

1242ProgramStateRef

CStringChecker::invalidateDestinationBufferNeverOverflows(

1244 auto

InvalidationTraitOperations =

1246 if

(MemRegion::FieldRegionKind == R->

getKind

())

1253 return

invalidateBufferAux(

C

, S, BufE, BufV, InvalidationTraitOperations);

1260 auto

InvalidationTraitOperations =

1270 return

invalidateBufferAux(

C

, S, BufE, BufV, InvalidationTraitOperations);

1277

InvalidationTraitOperations) {

1278

std::optional<Loc> L =

V

.getAs<

Loc

>();

1290 if

(

const ElementRegion

*ER = dyn_cast<ElementRegion>(R)) {

1298 bool

CausesPointerEscape = InvalidationTraitOperations(ITraits, R);

1300 return

State->invalidateRegions(R,

E

,

C

.blockCount(), LCtx,

1301

CausesPointerEscape,

nullptr

,

nullptr

,

1308 return

State->killBinding(*L);

1311bool

CStringChecker::SummarizeRegion(raw_ostream &os,

ASTContext

&Ctx,

1314 case

MemRegion::FunctionCodeRegionKind: {

1315 if

(

const auto

*FD = cast<FunctionCodeRegion>(MR)->getDecl())

1316

os <<

"the address of the function '"

<< *FD <<

'\''

;

1318

os <<

"the address of a function"

;

1321 case

MemRegion::BlockCodeRegionKind:

1322

os <<

"block text"

;

1324 case

MemRegion::BlockDataRegionKind:

1327 case

MemRegion::CXXThisRegionKind:

1328 case

MemRegion::CXXTempObjectRegionKind:

1329

os <<

"a C++ temp object of type " 1330

<< cast<TypedValueRegion>(MR)->getValueType();

1332 case

MemRegion::NonParamVarRegionKind:

1333

os <<

"a variable of type"

<< cast<TypedValueRegion>(MR)->getValueType();

1335 case

MemRegion::ParamVarRegionKind:

1336

os <<

"a parameter of type"

<< cast<TypedValueRegion>(MR)->getValueType();

1338 case

MemRegion::FieldRegionKind:

1339

os <<

"a field of type "

<< cast<TypedValueRegion>(MR)->getValueType();

1341 case

MemRegion::ObjCIvarRegionKind:

1342

os <<

"an instance variable of type " 1343

<< cast<TypedValueRegion>(MR)->getValueType();

1350bool

CStringChecker::memsetAux(

const Expr

*DstBuffer,

SVal

CharVal,

1353 SVal

MemVal =

C

.getSVal(DstBuffer);

1354 SVal

SizeVal =

C

.getSVal(Size);

1364 const MemRegion

*BR = Offset.getRegion();

1366

std::optional<NonLoc> SizeNL = SizeVal.

getAs

<

NonLoc

>();

1375 if

(Offset.isValid() && !Offset.hasSymbolicOffset() &&

1376

Offset.getOffset() == 0) {

1381

std::tie(StateWholeReg, StateNotWholeReg) =

1382

State->assume(svalBuilder.

evalEQ

(State, SizeDV, *SizeNL));

1389

std::tie(StateNullChar, StateNonNullChar) =

1392 if

(StateWholeReg && !StateNotWholeReg && StateNullChar &&

1393

!StateNonNullChar) {

1400

State = State->bindDefaultZero(svalBuilder.

makeLoc

(BR),

1401 C

.getLocationContext());

1405

State = invalidateDestinationBufferBySize(

C

, State, DstBuffer, MemVal,

1406

SizeVal,

Size

->getType());

1409 if

(StateNullChar && !StateNonNullChar) {

1412

State = setCStringLength(State, MR,

1414

}

else if

(!StateNullChar && StateNonNullChar) {

1416

CStringChecker::getTag(), MR, DstBuffer, Ctx.

getSizeType

(),

1417 C

.getLocationContext(),

C

.blockCount());

1424

State = setCStringLength(

1431

State = invalidateDestinationBufferBySize(

C

, State, DstBuffer, MemVal,

1432

SizeVal,

Size

->getType());

1443

DestinationArgExpr Dest,

1444

SourceArgExpr Source,

bool

Restricted,

1445 bool

IsMempcpy, CharKind CK)

const

{

1446

CurrentFunctionDescription =

"memory copy function"

;

1450 SVal

sizeVal = state->getSVal(

Size

.Expression, LCtx);

1454

std::tie(stateZeroSize, stateNonZeroSize) =

1455

assumeZero(

C

, state, sizeVal, sizeTy);

1458 SVal

destVal = state->getSVal(Dest.Expression, LCtx);

1462 if

(stateZeroSize && !stateNonZeroSize) {

1464

stateZeroSize->BindExpr(

Call

.getOriginExpr(), LCtx, destVal);

1465 C

.addTransition(stateZeroSize);

1470 if

(stateNonZeroSize) {

1474

state = stateNonZeroSize;

1478

state = checkNonNull(

C

, state, Dest, destVal);

1483 SVal

srcVal = state->getSVal(Source.Expression, LCtx);

1487

state = checkNonNull(

C

, state, Source, srcVal);

1492

state = CheckBufferAccess(

C

, state, Dest, Size, AccessKind::write, CK);

1493

state = CheckBufferAccess(

C

, state, Source, Size, AccessKind::read, CK);

1496

state = CheckOverlap(

C

, state, Size, Dest, Source, CK);

1507 QualType

CharPtrTy = getCharPtrType(Ctx, CK);

1508 SVal

DestRegCharVal =

1509

SvalBuilder.

evalCast

(destVal, CharPtrTy, Dest.Expression->getType());

1510 SVal

lastElement =

C

.getSValBuilder().evalBinOp(

1511

state, BO_Add, DestRegCharVal, sizeVal, Dest.Expression->getType());

1515

lastElement =

C

.getSValBuilder().conjureSymbolVal(

1516 nullptr

,

Call

.getOriginExpr(), LCtx,

C

.blockCount());

1519

state = state->BindExpr(

Call

.getOriginExpr(), LCtx, lastElement);

1523

state = state->BindExpr(

Call

.getOriginExpr(), LCtx, destVal);

1532

state = invalidateDestinationBufferBySize(

1533 C

, state, Dest.Expression,

C

.getSVal(Dest.Expression), sizeVal,

1534 Size

.Expression->getType());

1538

state = invalidateSourceBuffer(

C

, state, Source.Expression,

1539 C

.getSVal(Source.Expression));

1541 C

.addTransition(state);

1546

CharKind CK)

const

{

1549

DestinationArgExpr Dest = {{

Call

.getArgExpr(0), 0}};

1550

SourceArgExpr Src = {{

Call

.getArgExpr(1), 1}};

1551

SizeArgExpr

Size

= {{

Call

.getArgExpr(2), 2}};

1555 constexpr bool

IsRestricted =

true

;

1556 constexpr bool

IsMempcpy =

false

;

1557

evalCopyCommon(

C

,

Call

, State, Size, Dest, Src, IsRestricted, IsMempcpy, CK);

1561

CharKind CK)

const

{

1564

DestinationArgExpr Dest = {{

Call

.getArgExpr(0), 0}};

1565

SourceArgExpr Src = {{

Call

.getArgExpr(1), 1}};

1566

SizeArgExpr

Size

= {{

Call

.getArgExpr(2), 2}};

1568 constexpr bool

IsRestricted =

true

;

1569 constexpr bool

IsMempcpy =

true

;

1570

evalCopyCommon(

C

,

Call

,

C

.getState(), Size, Dest, Src, IsRestricted,

1575

CharKind CK)

const

{

1578

DestinationArgExpr Dest = {{

Call

.getArgExpr(0), 0}};

1579

SourceArgExpr Src = {{

Call

.getArgExpr(1), 1}};

1580

SizeArgExpr

Size

= {{

Call

.getArgExpr(2), 2}};

1582 constexpr bool

IsRestricted =

false

;

1583 constexpr bool

IsMempcpy =

false

;

1584

evalCopyCommon(

C

,

Call

,

C

.getState(), Size, Dest, Src, IsRestricted,

1590

SourceArgExpr Src{{

Call

.getArgExpr(0), 0}};

1591

DestinationArgExpr Dest = {{

Call

.getArgExpr(1), 1}};

1592

SizeArgExpr

Size

= {{

Call

.getArgExpr(2), 2}};

1594 constexpr bool

IsRestricted =

false

;

1595 constexpr bool

IsMempcpy =

false

;

1596

evalCopyCommon(

C

,

Call

,

C

.getState(), Size, Dest, Src, IsRestricted,

1597

IsMempcpy, CharKind::Regular);

1601

CharKind CK)

const

{

1603

CurrentFunctionDescription =

"memory comparison function"

;

1605

AnyArgExpr

Left

= {

Call

.getArgExpr(0), 0};

1606

AnyArgExpr

Right

= {

Call

.getArgExpr(1), 1};

1607

SizeArgExpr

Size

= {{

Call

.getArgExpr(2), 2}};

1614 SVal

sizeVal = State->getSVal(

Size

.Expression, LCtx);

1618

std::tie(stateZeroSize, stateNonZeroSize) =

1619

assumeZero(

C

, State, sizeVal, sizeTy);

1623 if

(stateZeroSize) {

1624

State = stateZeroSize;

1625

State = State->BindExpr(

Call

.getOriginExpr(), LCtx,

1626

Builder.makeZeroVal(

Call

.getResultType()));

1627 C

.addTransition(State);

1631 if

(stateNonZeroSize) {

1632

State = stateNonZeroSize;

1643

std::tie(SameBuffer, NotSameBuffer) =

1644

State->assume(Builder.evalEQ(State, LV, RV));

1648 if

(SameBuffer && !NotSameBuffer) {

1650

State = CheckBufferAccess(

C

, State, Left, Size, AccessKind::read);

1652

State = SameBuffer->BindExpr(

Call

.getOriginExpr(), LCtx,

1653

Builder.makeZeroVal(

Call

.getResultType()));

1654 C

.addTransition(State);

1661

assert(NotSameBuffer);

1662

State = CheckBufferAccess(

C

, State, Right, Size, AccessKind::read, CK);

1663

State = CheckBufferAccess(

C

, State, Left, Size, AccessKind::read, CK);

1666 SVal

CmpV = Builder.conjureSymbolVal(

nullptr

,

Call

.getOriginExpr(), LCtx,

1668

State = State->BindExpr(

Call

.getOriginExpr(), LCtx, CmpV);

1669 C

.addTransition(State);

1677

evalstrLengthCommon(

C

,

Call

,

false

);

1683

evalstrLengthCommon(

C

,

Call

,

true

);

1688 bool

IsStrnlen)

const

{

1689

CurrentFunctionDescription =

"string length function"

;

1694 const Expr

*maxlenExpr =

Call

.getArgExpr(1);

1695 SVal

maxlenVal = state->getSVal(maxlenExpr, LCtx);

1698

std::tie(stateZeroSize, stateNonZeroSize) =

1699

assumeZero(

C

, state, maxlenVal, maxlenExpr->

getType

());

1703 if

(stateZeroSize) {

1704 SVal

zero =

C

.getSValBuilder().makeZeroVal(

Call

.getResultType());

1705

stateZeroSize = stateZeroSize->BindExpr(

Call

.getOriginExpr(), LCtx, zero);

1706 C

.addTransition(stateZeroSize);

1710 if

(!stateNonZeroSize)

1714

state = stateNonZeroSize;

1718

AnyArgExpr Arg = {

Call

.getArgExpr(0), 0};

1719 SVal

ArgVal = state->getSVal(Arg.Expression, LCtx);

1720

state = checkNonNull(

C

, state, Arg, ArgVal);

1725 SVal

strLength = getCStringLength(

C

, state, Arg.Expression, ArgVal);

1737 QualType

cmpTy =

C

.getSValBuilder().getConditionType();

1741 const Expr

*maxlenExpr =

Call

.getArgExpr(1);

1742 SVal

maxlenVal = state->getSVal(maxlenExpr, LCtx);

1744

std::optional<NonLoc> strLengthNL = strLength.

getAs

<

NonLoc

>();

1745

std::optional<NonLoc> maxlenValNL = maxlenVal.

getAs

<

NonLoc

>();

1747 if

(strLengthNL && maxlenValNL) {

1751

std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(

1753

.evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)

1756 if

(stateStringTooLong && !stateStringNotTooLong) {

1758

result = *maxlenValNL;

1759

}

else if

(stateStringNotTooLong && !stateStringTooLong) {

1761

result = *strLengthNL;

1770

result =

C

.getSValBuilder().conjureSymbolVal(

1771 nullptr

,

Call

.getOriginExpr(), LCtx,

C

.blockCount());

1775

state = state->assume(

C

.getSValBuilder().evalBinOpNN(

1776

state, BO_LE, resultNL, *strLengthNL, cmpTy)

1781

state = state->assume(

C

.getSValBuilder().evalBinOpNN(

1782

state, BO_LE, resultNL, *maxlenValNL, cmpTy)

1794

result =

C

.getSValBuilder().conjureSymbolVal(

1795 nullptr

,

Call

.getOriginExpr(), LCtx,

C

.blockCount());

1800

assert(!result.

isUnknown

() &&

"Should have conjured a value by now"

);

1801

state = state->BindExpr(

Call

.getOriginExpr(), LCtx, result);

1802 C

.addTransition(state);

1808

evalStrcpyCommon(

C

,

Call

,

1811

ConcatFnKind::none);

1817

evalStrcpyCommon(

C

,

Call

,

1820

ConcatFnKind::none);

1826

evalStrcpyCommon(

C

,

Call

,

1829

ConcatFnKind::none);

1835

evalStrcpyCommon(

C

,

Call

,

1845

evalStrcpyCommon(

C

,

Call

,

1848

ConcatFnKind::strcat);

1854

evalStrcpyCommon(

C

,

Call

,

1857

ConcatFnKind::strcat);

1865

evalStrcpyCommon(

C

,

Call

,

1868

ConcatFnKind::strlcat,

1873 bool

ReturnEnd,

bool

IsBounded,

1874

ConcatFnKind appendK,

1875 bool

returnPtr)

const

{

1876 if

(appendK == ConcatFnKind::none)

1877

CurrentFunctionDescription =

"string copy function"

;

1879

CurrentFunctionDescription =

"string concatenation function"

;

1885

DestinationArgExpr Dst = {{

Call

.getArgExpr(0), 0}};

1886 SVal

DstVal = state->getSVal(Dst.Expression, LCtx);

1887

state = checkNonNull(

C

, state, Dst, DstVal);

1892

SourceArgExpr srcExpr = {{

Call

.getArgExpr(1), 1}};

1893 SVal

srcVal = state->getSVal(srcExpr.Expression, LCtx);

1894

state = checkNonNull(

C

, state, srcExpr, srcVal);

1899 SVal

strLength = getCStringLength(

C

, state, srcExpr.Expression, srcVal);

1900

std::optional<NonLoc> strLengthNL = strLength.

getAs

<

NonLoc

>();

1903 SVal

dstStrLength = getCStringLength(

C

, state, Dst.Expression, DstVal);

1904

std::optional<NonLoc> dstStrLengthNL = dstStrLength.getAs<

NonLoc

>();

1919 const char

*boundWarning =

nullptr

;

1923

SizeArgExpr SrcExprAsSizeDummy = {

1924

{srcExpr.Expression, srcExpr.ArgumentIndex}};

1925

state = CheckOverlap(

1927

(IsBounded ? SizeArgExpr{{

Call

.getArgExpr(2), 2}} : SrcExprAsSizeDummy),

1936

SizeArgExpr lenExpr = {{

Call

.getArgExpr(2), 2}};

1937 SVal

lenVal = state->getSVal(lenExpr.Expression, LCtx);

1941

svalBuilder.

evalCast

(lenVal, sizeTy, lenExpr.Expression->getType());

1943

std::optional<NonLoc> lenValNL = lenVal.

getAs

<

NonLoc

>();

1947 if

(strLengthNL && lenValNL) {

1949 case

ConcatFnKind::none:

1950 case

ConcatFnKind::strcat: {

1955

std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(

1957

.evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)

1958

.castAs<DefinedOrUnknownSVal>());

1960 if

(stateSourceTooLong && !stateSourceNotTooLong) {

1963

state = stateSourceTooLong;

1964

amountCopied = lenVal;

1966

}

else if

(!stateSourceTooLong && stateSourceNotTooLong) {

1968

state = stateSourceNotTooLong;

1969

amountCopied = strLength;

1973 case

ConcatFnKind::strlcat:

1974 if

(!dstStrLengthNL)

1979

*dstStrLengthNL, sizeTy);

1980 if

(!isa<NonLoc>(freeSpace))

1983

svalBuilder.

evalBinOp

(state, BO_Sub, freeSpace,

1984

svalBuilder.

makeIntVal

(1, sizeTy), sizeTy);

1985

std::optional<NonLoc> freeSpaceNL = freeSpace.

getAs

<

NonLoc

>();

1992

state, BO_LE, *strLengthNL, *freeSpaceNL, cmpTy);

1995

std::tie(TrueState, FalseState) =

1999 if

(TrueState && !FalseState) {

2000

amountCopied = strLength;

2004 if

(!TrueState && FalseState) {

2005

amountCopied = freeSpace;

2008 if

(TrueState && FalseState)

2016 case

ConcatFnKind::strcat:

2022 if

(dstStrLength.isUndef())

2025 if

(dstStrLengthNL) {

2027

state, BO_Add, *lenValNL, *dstStrLengthNL, sizeTy);

2029

boundWarning =

"Size argument is greater than the free space in the " 2030 "destination buffer"

;

2033 case

ConcatFnKind::none:

2034 case

ConcatFnKind::strlcat:

2044

std::tie(StateZeroSize, StateNonZeroSize) =

2045

assumeZero(

C

, state, *lenValNL, sizeTy);

2048 if

(StateZeroSize && !StateNonZeroSize) {

2051

StateZeroSize->BindExpr(

Call

.getOriginExpr(), LCtx, DstVal);

2053 if

(appendK == ConcatFnKind::none) {

2055

StateZeroSize = StateZeroSize->BindExpr(

Call

.getOriginExpr(),

2060

state, BO_Add, strLength, dstStrLength, sizeTy);

2062

StateZeroSize->BindExpr(

Call

.getOriginExpr(), LCtx, retSize);

2065 C

.addTransition(StateZeroSize);

2073

maxLastElementIndex =

2074

svalBuilder.

evalBinOpNN

(state, BO_Sub, *lenValNL, one, sizeTy);

2075

boundWarning =

"Size argument is greater than the length of the " 2076 "destination buffer"

;

2083

amountCopied = strLength;

2094 if

(appendK == ConcatFnKind::none && !returnPtr) {

2096

strlRetVal = strLength;

2102 if

(appendK != ConcatFnKind::none) {

2105 if

(dstStrLength.isUndef())

2108 if

(appendK == ConcatFnKind::strlcat && dstStrLengthNL && strLengthNL) {

2109

strlRetVal = svalBuilder.

evalBinOpNN

(state, BO_Add, *strLengthNL,

2110

*dstStrLengthNL, sizeTy);

2113

std::optional<NonLoc> amountCopiedNL = amountCopied.

getAs

<

NonLoc

>();

2116 if

(amountCopiedNL && dstStrLengthNL) {

2118

state = checkAdditionOverflow(

C

, state, *amountCopiedNL, *dstStrLengthNL);

2122

finalStrLength = svalBuilder.

evalBinOpNN

(state, BO_Add, *amountCopiedNL,

2123

*dstStrLengthNL, sizeTy);

2132

getCStringLength(

C

, state,

Call

.getOriginExpr(), DstVal,

true

);

2133

assert(!finalStrLength.

isUndef

());

2135 if

(std::optional<NonLoc> finalStrLengthNL =

2137 if

(amountCopiedNL && appendK == ConcatFnKind::none) {

2141

state, BO_GE, *finalStrLengthNL, *amountCopiedNL, cmpTy);

2148 if

(dstStrLengthNL && appendK != ConcatFnKind::none) {

2166

finalStrLength = amountCopied;

2174

Result = (ReturnEnd ?

UnknownVal

() : DstVal);

2176 if

(appendK == ConcatFnKind::strlcat || appendK == ConcatFnKind::none)

2178

Result = strlRetVal;

2180

Result = finalStrLength;

2187 if

(std::optional<loc::MemRegionVal> dstRegVal =

2189 QualType

ptrTy = Dst.Expression->getType();

2193 if

(std::optional<NonLoc> maxLastNL = maxLastElementIndex.

getAs

<

NonLoc

>()) {

2194 SVal

maxLastElement =

2195

svalBuilder.

evalBinOpLN

(state, BO_Add, *dstRegVal, *maxLastNL, ptrTy);

2198

state = CheckLocation(

C

, state, Dst, DstVal, AccessKind::write);

2202

state = CheckLocation(

C

, state, Dst, maxLastElement, AccessKind::write);

2208 if

(std::optional<NonLoc> knownStrLength = finalStrLength.

getAs

<

NonLoc

>()) {

2209 SVal

lastElement = svalBuilder.

evalBinOpLN

(state, BO_Add, *dstRegVal,

2210

*knownStrLength, ptrTy);

2213 if

(!boundWarning) {

2215

state = CheckLocation(

C

, state, Dst, DstVal, AccessKind::write);

2219

state = CheckLocation(

C

, state, Dst, lastElement, AccessKind::write);

2225 if

(returnPtr && ReturnEnd)

2226

Result = lastElement;

2236

state = invalidateDestinationBufferBySize(

C

, state, Dst.Expression,

2237

*dstRegVal, amountCopied,

2238 C

.getASTContext().getSizeType());

2242

state = invalidateSourceBuffer(

C

, state, srcExpr.Expression, srcVal);

2245 if

(IsBounded && (appendK == ConcatFnKind::none)) {

2250 if

(amountCopied != strLength)

2253

state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);

2261 if

(ReturnEnd && Result.isUnknown()) {

2267

state = state->BindExpr(

Call

.getOriginExpr(), LCtx, Result);

2268 C

.addTransition(state);

2274

evalStrcmpCommon(

C

,

Call

,

false

,

false

);

2280

evalStrcmpCommon(

C

,

Call

,

true

,

false

);

2286

evalStrcmpCommon(

C

,

Call

,

false

,

true

);

2292

evalStrcmpCommon(

C

,

Call

,

true

,

true

);

2296 bool

IsBounded,

bool

IgnoreCase)

const

{

2297

CurrentFunctionDescription =

"string comparison function"

;

2302

AnyArgExpr

Left

= {

Call

.getArgExpr(0), 0};

2303 SVal

LeftVal = state->getSVal(

Left

.Expression, LCtx);

2304

state = checkNonNull(

C

, state, Left, LeftVal);

2309

AnyArgExpr

Right

= {

Call

.getArgExpr(1), 1};

2310 SVal

RightVal = state->getSVal(

Right

.Expression, LCtx);

2311

state = checkNonNull(

C

, state, Right, RightVal);

2316 SVal

LeftLength = getCStringLength(

C

, state,

Left

.Expression, LeftVal);

2321 SVal

RightLength = getCStringLength(

C

, state,

Right

.Expression, RightVal);

2335

std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);

2341

StSameBuf->BindExpr(

Call

.getOriginExpr(), LCtx,

2342

svalBuilder.makeZeroVal(

Call

.getResultType()));

2343 C

.addTransition(StSameBuf);

2350

assert(StNotSameBuf);

2351

state = StNotSameBuf;

2358

getCStringLiteral(

C

, state,

Left

.Expression, LeftVal);

2360

getCStringLiteral(

C

, state,

Right

.Expression, RightVal);

2361 bool

canComputeResult =

false

;

2362 SVal

resultVal = svalBuilder.conjureSymbolVal(

nullptr

,

Call

.getOriginExpr(),

2363

LCtx,

C

.blockCount());

2365 if

(LeftStrLiteral && RightStrLiteral) {

2366

StringRef LeftStrRef = LeftStrLiteral->

getString

();

2367

StringRef RightStrRef = RightStrLiteral->

getString

();

2371 const Expr

*lenExpr =

Call

.getArgExpr(2);

2372 SVal

lenVal = state->getSVal(lenExpr, LCtx);

2375 if

(

const

llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {

2377

LeftStrRef = LeftStrRef.substr(0, (

size_t

)len->getZExtValue());

2378

RightStrRef = RightStrRef.substr(0, (

size_t

)len->getZExtValue());

2379

canComputeResult =

true

;

2383

canComputeResult =

true

;

2386 if

(canComputeResult) {

2388 size_t

s1Term = LeftStrRef.find(

'\0'

);

2389 if

(s1Term != StringRef::npos)

2390

LeftStrRef = LeftStrRef.substr(0, s1Term);

2392 size_t

s2Term = RightStrRef.find(

'\0'

);

2393 if

(s2Term != StringRef::npos)

2394

RightStrRef = RightStrRef.substr(0, s2Term);

2397 int

compareRes = IgnoreCase ? LeftStrRef.compare_insensitive(RightStrRef)

2398

: LeftStrRef.compare(RightStrRef);

2402 if

(compareRes == 0) {

2403

resultVal = svalBuilder.makeIntVal(compareRes,

Call

.getResultType());

2406 DefinedSVal

zeroVal = svalBuilder.makeIntVal(0,

Call

.getResultType());

2410 SVal

compareWithZero =

2411

svalBuilder.evalBinOp(state, op, resultVal, zeroVal,

2412

svalBuilder.getConditionType());

2414

state = state->assume(compareWithZeroVal,

true

);

2419

state = state->BindExpr(

Call

.getOriginExpr(), LCtx, resultVal);

2422 C

.addTransition(state);

2429

SourceArgExpr SearchStrPtr = {{

Call

.getArgExpr(0), 0}};

2432 if

(CharPtrTy.

isNull

() ||

Call

.getResultType().getUnqualifiedType() !=

2436

CurrentFunctionDescription =

"strsep()"

;

2442 SVal

SearchStrVal = State->getSVal(SearchStrPtr.Expression, LCtx);

2443

State = checkNonNull(

C

, State, SearchStrPtr, SearchStrVal);

2448

AnyArgExpr DelimStr = {

Call

.getArgExpr(1), 1};

2449 SVal

DelimStrVal = State->getSVal(DelimStr.Expression, LCtx);

2450

State = checkNonNull(

C

, State, DelimStr, DelimStrVal);

2456 if

(std::optional<Loc> SearchStrLoc = SearchStrVal.

getAs

<

Loc

>()) {

2458

Result = State->getSVal(*SearchStrLoc, CharPtrTy);

2463

State = invalidateDestinationBufferNeverOverflows(

2464 C

, State, SearchStrPtr.Expression, Result);

2469

State->bindLoc(*SearchStrLoc,

2471

LCtx, CharPtrTy,

C

.blockCount()),

2481

State = State->BindExpr(

Call

.getOriginExpr(), LCtx, Result);

2482 C

.addTransition(State);

2488

evalStdCopyCommon(

C

,

Call

);

2493

evalStdCopyCommon(

C

,

Call

);

2498 if

(!

Call

.getArgExpr(2)->getType()->isPointerType())

2511 const Expr

*Dst =

Call

.getArgExpr(2);

2512 SVal

DstVal = State->getSVal(Dst, LCtx);

2516

invalidateDestinationBufferAlwaysEscapeSuperRegion(

C

, State, Dst, DstVal);

2522

State = State->BindExpr(

Call

.getOriginExpr(), LCtx, ResultVal);

2524 C

.addTransition(State);

2530

CurrentFunctionDescription =

"memory set function"

;

2532

DestinationArgExpr Buffer = {{

Call

.getArgExpr(0), 0}};

2533

AnyArgExpr CharE = {

Call

.getArgExpr(1), 1};

2534

SizeArgExpr

Size

= {{

Call

.getArgExpr(2), 2}};

2540 SVal

SizeVal =

C

.getSVal(

Size

.Expression);

2544

std::tie(ZeroSize, NonZeroSize) = assumeZero(

C

, State, SizeVal, SizeTy);

2547 SVal

BufferPtrVal =

C

.getSVal(Buffer.Expression);

2551 if

(ZeroSize && !NonZeroSize) {

2552

ZeroSize = ZeroSize->BindExpr(

Call

.getOriginExpr(), LCtx, BufferPtrVal);

2553 C

.addTransition(ZeroSize);

2559

State = checkNonNull(

C

, NonZeroSize, Buffer, BufferPtrVal);

2563

State = CheckBufferAccess(

C

, State, Buffer, Size, AccessKind::write);

2570 if

(!memsetAux(Buffer.Expression,

C

.getSVal(CharE.Expression),

2571 Size

.Expression,

C

, State))

2574

State = State->BindExpr(

Call

.getOriginExpr(), LCtx, BufferPtrVal);

2575 C

.addTransition(State);

2579

CurrentFunctionDescription =

"memory clearance function"

;

2581

DestinationArgExpr Buffer = {{

Call

.getArgExpr(0), 0}};

2582

SizeArgExpr

Size

= {{

Call

.getArgExpr(1), 1}};

2583 SVal Zero

=

C

.getSValBuilder().makeZeroVal(

C

.getASTContext().IntTy);

2588 SVal

SizeVal =

C

.getSVal(

Size

.Expression);

2592

std::tie(StateZeroSize, StateNonZeroSize) =

2593

assumeZero(

C

, State, SizeVal, SizeTy);

2597 if

(StateZeroSize && !StateNonZeroSize) {

2598 C

.addTransition(StateZeroSize);

2603 SVal

MemVal =

C

.getSVal(Buffer.Expression);

2607

State = checkNonNull(

C

, StateNonZeroSize, Buffer, MemVal);

2611

State = CheckBufferAccess(

C

, State, Buffer, Size, AccessKind::write);

2615 if

(!memsetAux(Buffer.Expression, Zero,

Size

.Expression,

C

, State))

2618 C

.addTransition(State);

2623

CurrentFunctionDescription =

"'sprintf'"

;

2624

evalSprintfCommon(

C

,

Call

,

false

);

2629

CurrentFunctionDescription =

"'snprintf'"

;

2630

evalSprintfCommon(

C

,

Call

,

true

);

2634 bool

IsBounded)

const

{

2636 const auto

*CE = cast<CallExpr>(

Call

.getOriginExpr());

2637

DestinationArgExpr Dest = {{

Call

.getArgExpr(0), 0}};

2639 const auto

NumParams =

Call

.parameters().size();

2640 if

(CE->getNumArgs() < NumParams) {

2645 const auto

AllArguments =

2646

llvm::make_range(CE->getArgs(), CE->getArgs() + CE->getNumArgs());

2647 const auto

VariadicArguments = drop_begin(enumerate(AllArguments), NumParams);

2649 for

(

const auto

&[ArgIdx, ArgExpr] : VariadicArguments) {

2652

!

type

->isAnyPointerType() ||

2653

!

type

->getPointeeType()->isAnyCharacterType())

2655

SourceArgExpr Source = {{ArgExpr,

unsigned

(ArgIdx)}};

2658

SizeArgExpr SrcExprAsSizeDummy = {

2659

{Source.Expression, Source.ArgumentIndex}};

2660

State = CheckOverlap(

2662

(IsBounded ? SizeArgExpr{{

Call

.getArgExpr(1), 1}} : SrcExprAsSizeDummy),

2668 C

.addTransition(State);

2675

CStringChecker::FnCheck CStringChecker::identifyCall(

const CallEvent

&

Call

,

2677 const auto

*CE = dyn_cast_or_null<CallExpr>(

Call

.getOriginExpr());

2685 if

(StdCopy.matches(

Call

))

2686 return

&CStringChecker::evalStdCopy;

2687 if

(StdCopyBackward.matches(

Call

))

2688 return

&CStringChecker::evalStdCopyBackward;

2694 for

(

auto

I : CE->arguments()) {

2700 const

FnCheck *Callback = Callbacks.lookup(

Call

);

2708

FnCheck Callback = identifyCall(

Call

,

C

);

2715

assert(isa<CallExpr>(

Call

.getOriginExpr()));

2716

Callback(

this

,

C

,

Call

);

2724 return C

.isDifferent();

2731 for

(

const auto

*I : DS->

decls

()) {

2732 const VarDecl

*

D

= dyn_cast<VarDecl>(I);

2737 if

(!

D

->getType()->isArrayType())

2743 if

(!isa<StringLiteral>(

Init

))

2746 Loc

VarLoc = state->getLValue(

D

,

C

.getLocationContext());

2752

assert(StrVal.

isValid

() &&

"Initializer string is unknown or undefined"

);

2756

state = state->set<CStringLength>(MR, strLength);

2759 C

.addTransition(state);

2769

CStringLengthTy Entries = state->get<CStringLength>();

2770 if

(Entries.isEmpty())

2778

Invalidated.insert(MR);

2780

SuperRegions.insert(MR);

2781 while

(

const SubRegion

*SR = dyn_cast<SubRegion>(MR)) {

2782

MR = SR->getSuperRegion();

2783

SuperRegions.insert(MR);

2787

CStringLengthTy::Factory &F = state->get_context<CStringLength>();

2790 for

(

const MemRegion

*MR : llvm::make_first_range(Entries)) {

2792 if

(SuperRegions.count(MR)) {

2793

Entries = F.remove(Entries, MR);

2799 while

(

const SubRegion

*SR = dyn_cast<SubRegion>(Super)) {

2800

Super = SR->getSuperRegion();

2801 if

(Invalidated.count(Super)) {

2802

Entries = F.remove(Entries, MR);

2808 return

state->set<CStringLength>(Entries);

2814

CStringLengthTy Entries = state->get<CStringLength>();

2816 for

(

SVal

Len : llvm::make_second_range(Entries)) {

2822void

CStringChecker::checkDeadSymbols(

SymbolReaper

&SR,

2825

CStringLengthTy Entries = state->get<CStringLength>();

2826 if

(Entries.isEmpty())

2829

CStringLengthTy::Factory &F = state->get_context<CStringLength>();

2830 for

(

auto

[Reg, Len] : Entries) {

2831 if

(

SymbolRef

Sym = Len.getAsSymbol()) {

2833

Entries = F.remove(Entries, Reg);

2837

state = state->set<CStringLength>(Entries);

2838 C

.addTransition(state);

2845bool

ento::shouldRegisterCStringModeling(

const CheckerManager

&mgr) {

2849#define REGISTER_CHECKER(name) \ 2850 void ento::register##name(CheckerManager &mgr) { \ 2851 CStringChecker *checker = mgr.getChecker<CStringChecker>(); \ 2852 checker->Filter.Check##name = true; \ 2853 checker->Filter.CheckName##name = mgr.getCurrentCheckerName(); \ 2856 bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }

Defines enum values for all the target-independent builtin functions.

static std::optional< NonLoc > getIndex(ProgramStateRef State, const ElementRegion *ER, CharKind CK)

#define REGISTER_CHECKER(name)

static void printIdxWithOrdinalSuffix(llvm::raw_ostream &Os, unsigned Idx)

#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)

Declares an immutable map of type NameTy, suitable for placement into the ProgramState.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

QualType getPointerType(QualType T) const

Return the uniqued reference to the type for a pointer to the specified type.

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

CanQualType getSizeType() const

Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

CanQualType UnsignedCharTy

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

Decl - This represents one declaration (or definition), e.g.

This represents one expression.

Represents a function declaration or definition.

It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

Stmt - This represents one statement.

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

StringLiteral - This represents a string literal expression, e.g.

unsigned getLength() const

StringRef getString() const

bool isPointerType() const

QualType getPointeeType() const

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

bool isIntegralOrEnumerationType() const

Determine whether this type is an integral or enumeration type.

Represents a variable declaration or definition.

A record of the "type" of an APSInt, used for conversions.

llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY

APSIntPtr getMaxValue(const llvm::APSInt &v)

std::optional< APSIntPtr > evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)

An immutable map from CallDescriptions to arbitrary data.

A CallDescription is a pattern that can be used to match calls based on the qualified name and the ar...

Represents an abstract call to a function or method along a particular path.

CHECKER * registerChecker(AT &&... Args)

Used to register checkers.

This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...

ElementRegion is used to represent both array elements and casts.

QualType getValueType() const override

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const RegionTy * castAs() const

RegionOffset getAsOffset() const

Compute the offset within the top level memory object.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

Put a diagnostic on return statement of all inlined functions for which the region of interest Region...

Information about invalidation for a particular region/symbol.

@ TK_PreserveContents

Tells that a region's contents is not changed.

@ TK_DoNotInvalidateSuperRegion

@ TK_SuppressEscape

Suppress pointer-escaping of a region.

void setTrait(SymbolRef Sym, InvalidationKinds IK)

Represent a region's offset within the top level base region.

DefinedOrUnknownSVal makeZeroVal(QualType type)

Construct an SVal representing '0' for the specified type.

BasicValueFactory & getBasicValueFactory()

virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy)=0

Create a new value which represents a binary expression with a memory location and non-location opera...

DefinedSVal getMetadataSymbolVal(const void *symbolTag, const MemRegion *region, const Expr *expr, QualType type, const LocationContext *LCtx, unsigned count)

virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy)=0

Create a new value which represents a binary expression with two memory location operands.

ASTContext & getContext()

nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)

QualType getArrayIndexType() const

loc::MemRegionVal makeLoc(SymbolRef sym)

virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0

Create a new value which represents a binary expression with two non- location operands.

SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)

Cast a given SVal to another SVal using given QualType's.

DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)

Create a new symbol with a unique 'name'.

QualType getConditionType() const

SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs)

NonLoc makeZeroArrayIndex()

SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)

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

std::optional< T > getAs() const

Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.

const MemRegion * getAsRegion() const

T castAs() const

Convert to the specified SVal type, asserting that this SVal is of the desired type.

StringRegion - Region associated with a StringLiteral.

LLVM_ATTRIBUTE_RETURNS_NONNULL const StringLiteral * getStringLiteral() const

SubRegion - A region that subsets another larger region.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const

llvm::iterator_range< symbol_iterator > symbols() const

A class responsible for cleaning up unused symbols.

bool isDead(SymbolRef sym)

Returns whether or not a symbol has been confirmed dead.

void markInUse(SymbolRef sym)

Marks a symbol as important to a checker.

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

__inline void unsigned int _2

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr

Matches expressions.

bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})

Attempts to add visitors to track expression value back to its point of origin.

const char *const UnixAPI

DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB)

llvm::DenseSet< SymbolRef > InvalidatedSymbols

bool Zero(InterpState &S, CodePtr OpPC)

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

LLVM_READONLY char toUppercase(char c)

Converts the given ASCII character to its uppercase equivalent.

const FunctionProtoType * T


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4