forked from OSchip/llvm-project
[analyzer] Perform escaping in RetainCountChecker on type mismatch even for inlined functions
The fix done in D55465 did not previously apply when the function was inlined. rdar://46889541 Differential Revision: https://reviews.llvm.org/D55976 llvm-svn: 349876
This commit is contained in:
parent
f508532627
commit
aecb371a0a
|
@ -502,6 +502,25 @@ static Optional<RefVal> refValFromRetEffect(RetEffect RE,
|
|||
return None;
|
||||
}
|
||||
|
||||
static bool isPointerToObject(QualType QT) {
|
||||
QualType PT = QT->getPointeeType();
|
||||
if (!PT.isNull())
|
||||
if (PT->getAsCXXRecordDecl())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Whether the tracked value should be escaped on a given call.
|
||||
/// OSObjects are escaped when passed to void * / etc.
|
||||
static bool shouldEscapeArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
|
||||
const RefVal *TrackedValue) {
|
||||
if (TrackedValue->getObjKind() != RetEffect::OS)
|
||||
return false;
|
||||
if (ArgIdx >= CE.parameters().size())
|
||||
return false;
|
||||
return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
|
||||
}
|
||||
|
||||
// We don't always get the exact modeling of the function with regards to the
|
||||
// retain count checker even when the function is inlined. For example, we need
|
||||
// to stop tracking the symbols which were marked with StopTrackingHard.
|
||||
|
@ -512,11 +531,16 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
|
|||
|
||||
// Evaluate the effect of the arguments.
|
||||
for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
|
||||
if (Summ.getArg(idx) == StopTrackingHard) {
|
||||
SVal V = CallOrMsg.getArgSVal(idx);
|
||||
if (SymbolRef Sym = V.getAsLocSymbol()) {
|
||||
SVal V = CallOrMsg.getArgSVal(idx);
|
||||
|
||||
if (SymbolRef Sym = V.getAsLocSymbol()) {
|
||||
bool ShouldRemoveBinding = Summ.getArg(idx) == StopTrackingHard;
|
||||
if (const RefVal *T = getRefBinding(state, Sym))
|
||||
if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T))
|
||||
ShouldRemoveBinding = true;
|
||||
|
||||
if (ShouldRemoveBinding)
|
||||
state = removeRefBinding(state, Sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,25 +598,6 @@ static ProgramStateRef updateOutParameter(ProgramStateRef State,
|
|||
return State;
|
||||
}
|
||||
|
||||
static bool isPointerToObject(QualType QT) {
|
||||
QualType PT = QT->getPointeeType();
|
||||
if (!PT.isNull())
|
||||
if (PT->getAsCXXRecordDecl())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Whether the tracked value should be escaped on a given call.
|
||||
/// OSObjects are escaped when passed to void * / etc.
|
||||
static bool shouldEscapeArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
|
||||
const RefVal *TrackedValue) {
|
||||
if (TrackedValue->getObjKind() != RetEffect::OS)
|
||||
return false;
|
||||
if (ArgIdx >= CE.parameters().size())
|
||||
return false;
|
||||
return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
|
||||
}
|
||||
|
||||
void RetainCountChecker::checkSummary(const RetainSummary &Summ,
|
||||
const CallEvent &CallOrMsg,
|
||||
CheckerContext &C) const {
|
||||
|
|
|
@ -90,7 +90,10 @@ struct OSMetaClassBase {
|
|||
static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
|
||||
};
|
||||
|
||||
typedef unsigned long MYTYPE;
|
||||
|
||||
void escape(void *);
|
||||
void escape_with_source(MYTYPE p) {}
|
||||
bool coin();
|
||||
|
||||
bool os_consume_violation_two_args(OS_CONSUME OSObject *obj, bool extra) {
|
||||
|
@ -139,6 +142,13 @@ void test_escaping_into_voidstar() {
|
|||
escape(obj);
|
||||
}
|
||||
|
||||
void test_escape_has_source() {
|
||||
OSObject *obj = new OSObject;
|
||||
if (obj)
|
||||
escape_with_source((MYTYPE)obj);
|
||||
return;
|
||||
}
|
||||
|
||||
void test_no_infinite_check_recursion(MyArray *arr) {
|
||||
OSObject *input = new OSObject;
|
||||
OSObject *o = arr->generateObject(input);
|
||||
|
|
Loading…
Reference in New Issue