[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
`}
`