[analyzer] Teach the MallocChecker about Glib API for two arguments · llvm-mirror/clang@a530e82 (original) (raw)

`@@ -177,7 +177,10 @@ class MallocChecker : public Checker<check::DeadSymbols,

`

177

177

` II_wcsdup(nullptr), II_win_wcsdup(nullptr), II_g_malloc(nullptr),

`

178

178

` II_g_malloc0(nullptr), II_g_realloc(nullptr), II_g_try_malloc(nullptr),

`

179

179

` II_g_try_malloc0(nullptr), II_g_try_realloc(nullptr),

`

180

``

`-

II_g_free(nullptr), II_g_memdup(nullptr) {}

`

``

180

`+

II_g_free(nullptr), II_g_memdup(nullptr), II_g_malloc_n(nullptr),

`

``

181

`+

II_g_malloc0_n(nullptr), II_g_realloc_n(nullptr),

`

``

182

`+

II_g_try_malloc_n(nullptr), II_g_try_malloc0_n(nullptr),

`

``

183

`+

II_g_try_realloc_n(nullptr) {}

`

181

184

``

182

185

`/// In pessimistic mode, the checker assumes that it does not know which

`

183

186

`/// functions might free the memory.

`

`@@ -241,7 +244,10 @@ class MallocChecker : public Checker<check::DeadSymbols,

`

241

244

` *II_if_nameindex, *II_if_freenameindex, *II_wcsdup,

`

242

245

` *II_win_wcsdup, *II_g_malloc, *II_g_malloc0,

`

243

246

` *II_g_realloc, *II_g_try_malloc, *II_g_try_malloc0,

`

244

``

`-

*II_g_try_realloc, *II_g_free, *II_g_memdup;

`

``

247

`+

*II_g_try_realloc, *II_g_free, *II_g_memdup,

`

``

248

`+

*II_g_malloc_n, *II_g_malloc0_n, *II_g_realloc_n,

`

``

249

`+

*II_g_try_malloc_n, *II_g_try_malloc0_n,

`

``

250

`+

*II_g_try_realloc_n;

`

245

251

`mutable Optional KernelZeroFlagVal;

`

246

252

``

247

253

`void initIdentifierInfo(ASTContext &C) const;

`

`@@ -321,9 +327,12 @@ class MallocChecker : public Checker<check::DeadSymbols,

`

321

327

`bool &ReleasedAllocated,

`

322

328

`bool ReturnsNullOnFailure = false) const;

`

323

329

``

324

``

`-

ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,

`

325

``

`-

bool FreesMemOnFailure,

`

326

``

`-

ProgramStateRef State) const;

`

``

330

`+

ProgramStateRef ReallocMemAux(CheckerContext &C, const CallExpr *CE,

`

``

331

`+

bool FreesMemOnFailure,

`

``

332

`+

ProgramStateRef State,

`

``

333

`+

bool SuffixWithN = false) const;

`

``

334

`+

static SVal evalMulForBufferSize(CheckerContext &C, const Expr *Blocks,

`

``

335

`+

const Expr *BlockBytes);

`

327

336

`static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,

`

328

337

` ProgramStateRef State);

`

329

338

``

`@@ -569,6 +578,12 @@ void MallocChecker::initIdentifierInfo(ASTContext &Ctx) const {

`

569

578

` II_g_try_realloc = &Ctx.Idents.get("g_try_realloc");

`

570

579

` II_g_free = &Ctx.Idents.get("g_free");

`

571

580

` II_g_memdup = &Ctx.Idents.get("g_memdup");

`

``

581

`+

II_g_malloc_n = &Ctx.Idents.get("g_malloc_n");

`

``

582

`+

II_g_malloc0_n = &Ctx.Idents.get("g_malloc0_n");

`

``

583

`+

II_g_realloc_n = &Ctx.Idents.get("g_realloc_n");

`

``

584

`+

II_g_try_malloc_n = &Ctx.Idents.get("g_try_malloc_n");

`

``

585

`+

II_g_try_malloc0_n = &Ctx.Idents.get("g_try_malloc0_n");

`

``

586

`+

II_g_try_realloc_n = &Ctx.Idents.get("g_try_realloc_n");

`

572

587

`}

`

573

588

``

574

589

`bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {

`

`@@ -617,7 +632,10 @@ bool MallocChecker::isCMemFunction(const FunctionDecl *FD,

`

617

632

` FunI == II_g_malloc || FunI == II_g_malloc0 ||

`

618

633

` FunI == II_g_realloc || FunI == II_g_try_malloc ||

`

619

634

` FunI == II_g_try_malloc0 || FunI == II_g_try_realloc ||

`

620

``

`-

FunI == II_g_memdup)

`

``

635

`+

FunI == II_g_memdup || FunI == II_g_malloc_n ||

`

``

636

`+

FunI == II_g_malloc0_n || FunI == II_g_realloc_n ||

`

``

637

`+

FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n ||

`

``

638

`+

FunI == II_g_try_realloc_n)

`

621

639

`return true;

`

622

640

` }

`

623

641

``

`@@ -767,6 +785,17 @@ llvm::Optional MallocChecker::performKernelMalloc(

`

767

785

`return None;

`

768

786

`}

`

769

787

``

``

788

`+

SVal MallocChecker::evalMulForBufferSize(CheckerContext &C, const Expr *Blocks,

`

``

789

`+

const Expr *BlockBytes) {

`

``

790

`+

SValBuilder &SB = C.getSValBuilder();

`

``

791

`+

SVal BlocksVal = C.getSVal(Blocks);

`

``

792

`+

SVal BlockBytesVal = C.getSVal(BlockBytes);

`

``

793

`+

ProgramStateRef State = C.getState();

`

``

794

`+

SVal TotalSize = SB.evalBinOp(State, BO_Mul, BlocksVal, BlockBytesVal,

`

``

795

`+

SB.getContext().getSizeType());

`

``

796

`+

return TotalSize;

`

``

797

`+

}

`

``

798

+

770

799

`void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {

`

771

800

`if (C.wasInlined)

`

772

801

`return;

`

`@@ -813,10 +842,10 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {

`

813

842

` State = ProcessZeroAllocation(C, CE, 0, State);

`

814

843

` } else if (FunI == II_realloc || FunI == II_g_realloc ||

`

815

844

` FunI == II_g_try_realloc) {

`

816

``

`-

State = ReallocMem(C, CE, false, State);

`

``

845

`+

State = ReallocMemAux(C, CE, false, State);

`

817

846

` State = ProcessZeroAllocation(C, CE, 1, State);

`

818

847

` } else if (FunI == II_reallocf) {

`

819

``

`-

State = ReallocMem(C, CE, true, State);

`

``

848

`+

State = ReallocMemAux(C, CE, true, State);

`

820

849

` State = ProcessZeroAllocation(C, CE, 1, State);

`

821

850

` } else if (FunI == II_calloc) {

`

822

851

` State = CallocMem(C, CE, State);

`

`@@ -874,6 +903,25 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {

`

874

903

`return;

`

875

904

` State = MallocMemAux(C, CE, CE->getArg(1), UndefinedVal(), State);

`

876

905

` State = ProcessZeroAllocation(C, CE, 1, State);

`

``

906

`+

} else if (FunI == II_g_malloc_n || FunI == II_g_try_malloc_n ||

`

``

907

`+

FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {

`

``

908

`+

if (CE->getNumArgs() < 2)

`

``

909

`+

return;

`

``

910

`+

SVal Init = UndefinedVal();

`

``

911

`+

if (FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {

`

``

912

`+

SValBuilder &SB = C.getSValBuilder();

`

``

913

`+

Init = SB.makeZeroVal(SB.getContext().CharTy);

`

``

914

`+

}

`

``

915

`+

SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));

`

``

916

`+

State = MallocMemAux(C, CE, TotalSize, Init, State);

`

``

917

`+

State = ProcessZeroAllocation(C, CE, 0, State);

`

``

918

`+

State = ProcessZeroAllocation(C, CE, 1, State);

`

``

919

`+

} else if (FunI == II_g_realloc_n || FunI == II_g_try_realloc_n) {

`

``

920

`+

if (CE->getNumArgs() < 3)

`

``

921

`+

return;

`

``

922

`+

State = ReallocMemAux(C, CE, false, State, true);

`

``

923

`+

State = ProcessZeroAllocation(C, CE, 1, State);

`

``

924

`+

State = ProcessZeroAllocation(C, CE, 2, State);

`

877

925

` }

`

878

926

` }

`

879

927

``

`@@ -1976,14 +2024,17 @@ void MallocChecker::ReportUseZeroAllocated(CheckerContext &C,

`

1976

2024

` }

`

1977

2025

`}

`

1978

2026

``

1979

``

`-

ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,

`

1980

``

`-

const CallExpr *CE,

`

1981

``

`-

bool FreesOnFail,

`

1982

``

`-

ProgramStateRef State) const {

`

``

2027

`+

ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C,

`

``

2028

`+

const CallExpr *CE,

`

``

2029

`+

bool FreesOnFail,

`

``

2030

`+

ProgramStateRef State,

`

``

2031

`+

bool SuffixWithN) const {

`

1983

2032

`if (!State)

`

1984

2033

`return nullptr;

`

1985

2034

``

1986

``

`-

if (CE->getNumArgs() < 2)

`

``

2035

`+

if (SuffixWithN && CE->getNumArgs() < 3)

`

``

2036

`+

return nullptr;

`

``

2037

`+

else if (CE->getNumArgs() < 2)

`

1987

2038

`return nullptr;

`

1988

2039

``

1989

2040

`const Expr *arg0Expr = CE->getArg(0);

`

`@@ -1998,20 +2049,19 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,

`

1998

2049

` DefinedOrUnknownSVal PtrEQ =

`

1999

2050

` svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());

`

2000

2051

``

2001

``

`-

// Get the size argument. If there is no size arg then give up.

`

``

2052

`+

// Get the size argument.

`

2002

2053

`const Expr *Arg1 = CE->getArg(1);

`

2003

``

`-

if (!Arg1)

`

2004

``

`-

return nullptr;

`

2005

2054

``

2006

2055

`// Get the value of the size argument.

`

2007

``

`-

SVal Arg1ValG = State->getSVal(Arg1, LCtx);

`

2008

``

`-

if (!Arg1ValG.getAs())

`

``

2056

`+

SVal TotalSize = State->getSVal(Arg1, LCtx);

`

``

2057

`+

if (SuffixWithN)

`

``

2058

`+

TotalSize = evalMulForBufferSize(C, Arg1, CE->getArg(2));

`

``

2059

`+

if (!TotalSize.getAs())

`

2009

2060

`return nullptr;

`

2010

``

`-

DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs();

`

2011

2061

``

2012

2062

`// Compare the size argument to 0.

`

2013

2063

` DefinedOrUnknownSVal SizeZero =

`

2014

``

`-

svalBuilder.evalEQ(State, Arg1Val,

`

``

2064

`+

svalBuilder.evalEQ(State, TotalSize.castAs(),

`

2015

2065

` svalBuilder.makeIntValWithPtrWidth(0, false));

`

2016

2066

``

2017

2067

` ProgramStateRef StatePtrIsNull, StatePtrNotNull;

`

`@@ -2025,8 +2075,8 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,

`

2025

2075

``

2026

2076

`// If the ptr is NULL and the size is not 0, the call is equivalent to

`

2027

2077

`// malloc(size).

`

2028

``

`-

if ( PrtIsNull && !SizeIsZero) {

`

2029

``

`-

ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1),

`

``

2078

`+

if (PrtIsNull && !SizeIsZero) {

`

``

2079

`+

ProgramStateRef stateMalloc = MallocMemAux(C, CE, TotalSize,

`

2030

2080

`UndefinedVal(), StatePtrIsNull);

`

2031

2081

`return stateMalloc;

`

2032

2082

` }

`

`@@ -2059,7 +2109,7 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,

`

2059

2109

`if (ProgramStateRef stateFree =

`

2060

2110

`FreeMemAux(C, CE, State, 0, false, ReleasedAllocated)) {

`

2061

2111

``

2062

``

`-

ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),

`

``

2112

`+

ProgramStateRef stateRealloc = MallocMemAux(C, CE, TotalSize,

`

2063

2113

`UnknownVal(), stateFree);

`

2064

2114

`if (!stateRealloc)

`

2065

2115

`return nullptr;

`

`@@ -2090,12 +2140,8 @@ ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE,

`

2090

2140

`return nullptr;

`

2091

2141

``

2092

2142

` SValBuilder &svalBuilder = C.getSValBuilder();

`

2093

``

`-

const LocationContext *LCtx = C.getLocationContext();

`

2094

``

`-

SVal count = State->getSVal(CE->getArg(0), LCtx);

`

2095

``

`-

SVal elementSize = State->getSVal(CE->getArg(1), LCtx);

`

2096

``

`-

SVal TotalSize = svalBuilder.evalBinOp(State, BO_Mul, count, elementSize,

`

2097

``

`-

svalBuilder.getContext().getSizeType());

`

2098

2143

` SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);

`

``

2144

`+

SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));

`

2099

2145

``

2100

2146

`return MallocMemAux(C, CE, TotalSize, zeroVal, State);

`

2101

2147

`}

`