@@ -1702,15 +1702,18 @@ MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallEvent &Call,
1702
1702
if (!State)
1703
1703
return nullptr ;
1704
1704
1705
- if (Att->getModule ()->getName () != " malloc" )
1706
- return nullptr ;
1705
+ // Preseve previous behavior when "malloc" class means AF_Malloc
1706
+ auto attrClassName = Att->getModule ()->getName ();
1707
+ auto AF = attrClassName == " malloc"
1708
+ ? AF_Malloc
1709
+ : AllocationFamily (AF_Custom, attrClassName);
1707
1710
1708
1711
if (!Att->args ().empty ()) {
1709
1712
return MallocMemAux (C, Call,
1710
1713
Call.getArgExpr (Att->args_begin ()->getASTIndex ()),
1711
- UndefinedVal (), State, AF_Malloc );
1714
+ UndefinedVal (), State, AF );
1712
1715
}
1713
- return MallocMemAux (C, Call, UnknownVal (), UndefinedVal (), State, AF_Malloc );
1716
+ return MallocMemAux (C, Call, UnknownVal (), UndefinedVal (), State, AF );
1714
1717
}
1715
1718
1716
1719
ProgramStateRef MallocChecker::MallocMemAux (CheckerContext &C,
@@ -1862,16 +1865,18 @@ ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
1862
1865
if (!State)
1863
1866
return nullptr ;
1864
1867
1865
- if (Att->getModule ()->getName () != " malloc" )
1866
- return nullptr ;
1868
+ // Preseve previous behavior when "malloc" class means AF_Malloc
1869
+ auto attrClassName = Att->getModule ()->getName ();
1870
+ auto AF = attrClassName == " malloc"
1871
+ ? AF_Malloc
1872
+ : AllocationFamily (AF_Custom, attrClassName);
1867
1873
1868
1874
bool IsKnownToBeAllocated = false ;
1869
1875
1870
1876
for (const auto &Arg : Att->args ()) {
1871
- ProgramStateRef StateI =
1872
- FreeMemAux (C, Call, State, Arg.getASTIndex (),
1873
- Att->getOwnKind () == OwnershipAttr::Holds,
1874
- IsKnownToBeAllocated, AF_Malloc);
1877
+ ProgramStateRef StateI = FreeMemAux (
1878
+ C, Call, State, Arg.getASTIndex (),
1879
+ Att->getOwnKind () == OwnershipAttr::Holds, IsKnownToBeAllocated, AF);
1875
1880
if (StateI)
1876
1881
State = StateI;
1877
1882
}
@@ -1909,6 +1914,33 @@ static bool didPreviousFreeFail(ProgramStateRef State,
1909
1914
return false ;
1910
1915
}
1911
1916
1917
+ static void printOwnershipTakesList (raw_ostream &os, CheckerContext &C,
1918
+ const Expr *E) {
1919
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1920
+ const FunctionDecl *FD = CE->getDirectCallee ();
1921
+ if (!FD)
1922
+ return ;
1923
+
1924
+ if (FD->hasAttrs ()) {
1925
+ bool attrPrinted = false ;
1926
+
1927
+ for (const auto *I : FD->specific_attrs <OwnershipAttr>()) {
1928
+ OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind ();
1929
+
1930
+ if (OwnKind == OwnershipAttr::Takes) {
1931
+ if (attrPrinted)
1932
+ os << " , " ;
1933
+ else
1934
+ os << " , which takes ownership of " ;
1935
+
1936
+ os << ' \' ' << I->getModule ()->getName () << " '" ;
1937
+ attrPrinted = true ;
1938
+ }
1939
+ }
1940
+ }
1941
+ }
1942
+ }
1943
+
1912
1944
static bool printMemFnName (raw_ostream &os, CheckerContext &C, const Expr *E) {
1913
1945
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1914
1946
// FIXME: This doesn't handle indirect calls.
@@ -1966,11 +1998,12 @@ static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family) {
1966
1998
case AF_InnerBuffer:
1967
1999
os << " container-specific allocator" ;
1968
2000
return ;
2001
+ case AF_Custom:
2002
+ os << Family.name ().value ();
2003
+ return ;
1969
2004
case AF_Alloca:
1970
2005
case AF_None:
1971
2006
llvm_unreachable (" not a deallocation expression" );
1972
- case AF_Custom:
1973
- llvm_unreachable (" not a deallocation expression" );
1974
2007
}
1975
2008
}
1976
2009
@@ -1991,11 +2024,12 @@ static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) {
1991
2024
case AF_InnerBuffer:
1992
2025
os << " container-specific deallocator" ;
1993
2026
return ;
2027
+ case AF_Custom:
2028
+ os << " function that takes ownership of '" << Family.name ().value () << " \' " ;
2029
+ return ;
1994
2030
case AF_Alloca:
1995
2031
case AF_None:
1996
2032
llvm_unreachable (" suspicious argument" );
1997
- case AF_Custom:
1998
- llvm_unreachable (" suspicious argument" );
1999
2033
}
2000
2034
}
2001
2035
@@ -2180,6 +2214,7 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family,
2180
2214
switch (Family.kind ()) {
2181
2215
case AF_Malloc:
2182
2216
case AF_Alloca:
2217
+ case AF_Custom:
2183
2218
case AF_IfNameIndex: {
2184
2219
if (ChecksEnabled[CK_MallocChecker])
2185
2220
return CK_MallocChecker;
@@ -2202,7 +2237,6 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family,
2202
2237
return CK_InnerPointerChecker;
2203
2238
return std::nullopt;
2204
2239
}
2205
- case AF_Custom:
2206
2240
case AF_None: {
2207
2241
llvm_unreachable (" no family" );
2208
2242
}
@@ -2432,6 +2466,8 @@ void MallocChecker::HandleMismatchedDealloc(CheckerContext &C,
2432
2466
2433
2467
if (printMemFnName (DeallocOs, C, DeallocExpr))
2434
2468
os << " , not " << DeallocOs.str ();
2469
+
2470
+ printOwnershipTakesList (os, C, DeallocExpr);
2435
2471
}
2436
2472
2437
2473
auto R = std::make_unique<PathSensitiveBugReport>(*BT_MismatchedDealloc,
@@ -3545,6 +3581,7 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
3545
3581
switch (Family.kind ()) {
3546
3582
case AF_Alloca:
3547
3583
case AF_Malloc:
3584
+ case AF_Custom:
3548
3585
case AF_CXXNew:
3549
3586
case AF_CXXNewArray:
3550
3587
case AF_IfNameIndex:
@@ -3585,8 +3622,7 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
3585
3622
}
3586
3623
Msg = OS.str ();
3587
3624
break ;
3588
- }
3589
- case AF_Custom:
3625
+ }
3590
3626
case AF_None:
3591
3627
llvm_unreachable (" Unhandled allocation family!" );
3592
3628
}
0 commit comments