Skip to content

Commit

Permalink
Stop tracking retain count of OSObject after escape to void * / other…
Browse files Browse the repository at this point in the history
… primitive types

Escaping to void * / uint64_t / others non-OSObject * should stop tracking,
as such functions can have heterogeneous semantics depending on context,
and can not always be annotated.

rdar://46439133

Differential Revision: https://reviews.llvm.org/D55465

llvm-svn: 348675
  • Loading branch information
George Karpenkov committed Dec 8, 2018
1 parent 4ce6d46 commit 041c9fa
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
Expand Up @@ -574,6 +574,25 @@ 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 {
Expand All @@ -592,6 +611,10 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
state = updateOutParameter(state, V, Effect);
} else if (SymbolRef Sym = V.getAsLocSymbol()) {
if (const RefVal *T = getRefBinding(state, Sym)) {

if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T))
Effect = StopTrackingHard;

state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
if (hasErr) {
ErrorRange = CallOrMsg.getArgSourceRange(idx);
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Analysis/osobject-retain-release.cpp
Expand Up @@ -89,6 +89,13 @@ struct OSMetaClassBase {
static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
};

void escape(void *);

void test_escaping_into_voidstar() {
OSObject *obj = new OSObject;
escape(obj);
}

void test_no_infinite_check_recursion(MyArray *arr) {
OSObject *input = new OSObject;
OSObject *o = arr->generateObject(input);
Expand Down

0 comments on commit 041c9fa

Please sign in to comment.