[analyzer][MallocChecker] PR46253: Correctly recognize standard realloc

https://bugs.llvm.org/show_bug.cgi?id=46253

This is an obvious hack because realloc isn't any more affected than other
functions modeled by MallocChecker (or any user of CallDescription really),
but the nice solution will take some time to implement.

Differential Revision: https://reviews.llvm.org/D81745
This commit is contained in:
Kirstóf Umann 2020-06-12 18:15:20 +02:00
parent 4799fb63b5
commit 1614e35408
2 changed files with 56 additions and 2 deletions

View File

@ -47,6 +47,7 @@
#include "AllocationState.h"
#include "InterCheckerAPI.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
@ -1037,9 +1038,44 @@ void MallocChecker::checkKernelMalloc(const CallEvent &Call,
C.addTransition(State);
}
void MallocChecker::checkRealloc(const CallEvent &Call,
CheckerContext &C,
static bool isStandardRealloc(const CallEvent &Call) {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(Call.getDecl());
assert(FD);
ASTContext &AC = FD->getASTContext();
if (isa<CXXMethodDecl>(FD))
return false;
return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(1)->getType().getDesugaredType(AC) ==
AC.getSizeType();
}
static bool isGRealloc(const CallEvent &Call) {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(Call.getDecl());
assert(FD);
ASTContext &AC = FD->getASTContext();
if (isa<CXXMethodDecl>(FD))
return false;
return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(1)->getType().getDesugaredType(AC) ==
AC.UnsignedLongTy;
}
void MallocChecker::checkRealloc(const CallEvent &Call, CheckerContext &C,
bool ShouldFreeOnFail) const {
// HACK: CallDescription currently recognizes non-standard realloc functions
// as standard because it doesn't check the type, or wether its a non-method
// function. This should be solved by making CallDescription smarter.
// Mind that this came from a bug report, and all other functions suffer from
// this.
// https://bugs.llvm.org/show_bug.cgi?id=46253
if (!isStandardRealloc(Call) && !isGRealloc(Call))
return;
ProgramStateRef State = C.getState();
State = ReallocMemAux(C, Call, ShouldFreeOnFail, State, AF_Malloc);
State = ProcessZeroAllocCheck(Call, 1, State);

View File

@ -172,3 +172,21 @@ void test_delete_ZERO_SIZE_PTR() {
// ZERO_SIZE_PTR is specially handled but only for malloc family
delete Ptr; // expected-warning{{Argument to 'delete' is a constant address (16)}}
}
namespace pr46253_class {
class a {
void *realloc(int, bool = false) { realloc(1); } // no-crash
};
} // namespace pr46253_class
namespace pr46253_retty{
void realloc(void *ptr, size_t size) { realloc(ptr, size); } // no-crash
} // namespace pr46253_retty
namespace pr46253_paramty{
void *realloc(void **ptr, size_t size) { realloc(ptr, size); } // no-crash
} // namespace pr46253_paramty
namespace pr46253_paramty2{
void *realloc(void *ptr, int size) { realloc(ptr, size); } // no-crash
} // namespace pr46253_paramty2