Bug 1691515 - Add MOZ_KNOWN_LIVE member annotation r=andi

Differential Revision: https://phabricator.services.mozilla.com/D107321
This commit is contained in:
Kagami Sascha Rosylight 2021-03-05 23:23:03 +00:00
parent c21715e694
commit a2323b59a0
11 changed files with 62 additions and 19 deletions

View File

@ -54,9 +54,8 @@
void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
auto Refcounted = qualType(hasDeclaration(cxxRecordDecl(isRefCounted())));
auto StackSmartPtr =
ignoreTrivials(declRefExpr(to(varDecl(hasAutomaticStorageDuration(),
hasType(isSmartPtrToRefCounted())))));
auto StackSmartPtr = ignoreTrivials(declRefExpr(to(varDecl(
hasAutomaticStorageDuration(), hasType(isSmartPtrToRefCounted())))));
auto ConstMemberOfThisSmartPtr =
memberExpr(hasType(isSmartPtrToRefCounted()), hasType(isConstQualified()),
hasObjectExpression(cxxThisExpr()));
@ -76,13 +75,17 @@ void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
// Params of the calling function are presumed live, because it itself should
// be MOZ_CAN_RUN_SCRIPT. Note that this is subject to
// https://bugzilla.mozilla.org/show_bug.cgi?id=1537656 a the moment.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1537656 at the moment.
auto KnownLiveParam = anyOf(
// "this" is OK
cxxThisExpr(),
// A parameter of the calling function is OK.
declRefExpr(to(parmVarDecl())));
auto KnownLiveMemberOfParam =
memberExpr(hasKnownLiveAnnotation(),
hasObjectExpression(ignoreTrivials(KnownLiveParam)));
// A matcher that matches various things that are known to be live directly,
// without making any assumptions about operators.
auto KnownLiveBase = anyOf(
@ -92,6 +95,8 @@ void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
MozKnownLiveCall,
// Params of the caller function.
KnownLiveParam,
// Members of the params that are marked as MOZ_KNOWN_LIVE
KnownLiveMemberOfParam,
// Constexpr things.
declRefExpr(to(varDecl(isConstexpr()))));

View File

@ -7,6 +7,7 @@ ATTR(moz_heap_class)
ATTR(moz_implicit)
ATTR(moz_inherit_type_annotations_from_template_args)
ATTR(moz_is_smartptr_to_refcounted)
ATTR(moz_known_live)
ATTR(moz_may_call_after_must_return)
ATTR(moz_must_override)
ATTR(moz_must_return_from_caller_if_this_is_arg)

View File

@ -420,6 +420,12 @@ AST_MATCHER(UsingDirectiveDecl, isUsingNamespaceMozillaJava) {
!FQName.compare(0, sizeof(PREFIX) - 1, PREFIX);
}
AST_MATCHER(MemberExpr, hasKnownLiveAnnotation) {
ValueDecl *Member = Node.getMemberDecl();
FieldDecl *Field = dyn_cast<FieldDecl>(Member);
return Field && hasCustomAttribute<moz_known_live>(Field);
}
} // namespace ast_matchers
} // namespace clang

View File

@ -619,3 +619,36 @@ struct DisallowMemberArgsViaReferenceAlias2 {
}
}
};
struct AllowMozKnownLiveMember {
public:
MOZ_KNOWN_LIVE RefCountedBase* mWhatever;
MOZ_CAN_RUN_SCRIPT void foo(RefCountedBase* aWhatever) {}
MOZ_CAN_RUN_SCRIPT void bar() {
foo(mWhatever);
}
};
struct AllowMozKnownLiveMemberParent : AllowMozKnownLiveMember {
MOZ_CAN_RUN_SCRIPT void baz() {
foo(mWhatever);
}
};
struct AllowMozKnownLiveParamMember {
public:
MOZ_CAN_RUN_SCRIPT void foo(AllowMozKnownLiveMember& aAllow) {
aAllow.foo(aAllow.mWhatever);
}
MOZ_CAN_RUN_SCRIPT void bar(AllowMozKnownLiveMemberParent& aAllowParent) {
aAllowParent.foo(aAllowParent.mWhatever);
}
};
struct DisallowMozKnownLiveMemberNotFromKnownLive {
AllowMozKnownLiveMember* mMember;
MOZ_CAN_RUN_SCRIPT void foo(RefCountedBase* aWhatever) {}
MOZ_CAN_RUN_SCRIPT void bar() {
foo(mMember->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mWhatever' is neither.}}
}
};

View File

@ -3105,8 +3105,8 @@ nsresult Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor) {
WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
if (keyEvent && keyEvent->mKeyCode == NS_VK_RETURN) {
nsEventStatus status = nsEventStatus_eIgnore;
rv = DispatchClickEvent(MOZ_KnownLive(aVisitor.mPresContext), keyEvent,
this, false, nullptr, &status);
rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this, false,
nullptr, &status);
if (NS_SUCCEEDED(rv)) {
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}

View File

@ -66,11 +66,9 @@ class MOZ_STACK_CLASS EventChainVisitor {
/**
* The prescontext, possibly nullptr.
* Note that the lifetime of mPresContext is guaranteed by the creators so
* that you can use this with MOZ_KnownLive() when you set argument
* of can-run-script methods to this.
* Note that the lifetime of mPresContext is guaranteed by the creators.
*/
nsPresContext* const mPresContext;
MOZ_KNOWN_LIVE nsPresContext* const mPresContext;
/**
* The WidgetEvent which is being dispatched. Never nullptr.
@ -307,7 +305,7 @@ class MOZ_STACK_CLASS EventChainPostVisitor final
// of this class is alive.
MOZ_CAN_RUN_SCRIPT
explicit EventChainPostVisitor(EventChainVisitor& aOther)
: EventChainVisitor(MOZ_KnownLive(aOther.mPresContext), aOther.mEvent,
: EventChainVisitor(aOther.mPresContext, aOther.mEvent,
MOZ_KnownLive(aOther.mDOMEvent),
aOther.mEventStatus) {}
};

View File

@ -4192,8 +4192,7 @@ class MOZ_STACK_CLASS ESMEventCB : public EventDispatchingCallback {
if (aVisitor.mPresContext) {
nsIFrame* frame = aVisitor.mPresContext->GetPrimaryFrameFor(mTarget);
if (frame) {
frame->HandleEvent(MOZ_KnownLive(aVisitor.mPresContext),
aVisitor.mEvent->AsGUIEvent(),
frame->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent->AsGUIEvent(),
&aVisitor.mEventStatus);
}
}

View File

@ -3796,7 +3796,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
// Checkbox and Radio try to submit on Enter press
if (keyEvent->mKeyCode != NS_VK_SPACE &&
aVisitor.mPresContext) {
MaybeSubmitForm(MOZ_KnownLive(aVisitor.mPresContext));
MaybeSubmitForm(aVisitor.mPresContext);
break; // If we are submitting, do not send click event
}
@ -3874,7 +3874,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
mType == NS_FORM_INPUT_NUMBER || IsDateTimeInputType(mType))) {
FireChangeEventIfNeeded();
if (aVisitor.mPresContext) {
rv = MaybeSubmitForm(MOZ_KnownLive(aVisitor.mPresContext));
rv = MaybeSubmitForm(aVisitor.mPresContext);
NS_ENSURE_SUCCESS(rv, rv);
}
}

View File

@ -162,8 +162,8 @@ nsresult HTMLLabelElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
// will actually create a new event.
EventFlags eventFlags;
eventFlags.mMultipleActionsPrevented = true;
DispatchClickEvent(MOZ_KnownLive(aVisitor.mPresContext), mouseEvent,
content, false, &eventFlags, &status);
DispatchClickEvent(aVisitor.mPresContext, mouseEvent, content, false,
&eventFlags, &status);
// Do we care about the status this returned? I don't think we do...
// Don't run another <label> off of this click
mouseEvent->mFlags.mMultipleActionsPrevented = true;

View File

@ -522,8 +522,7 @@ class MOZ_STACK_CLASS nsPresShellEventCB : public EventDispatchingCallback {
frame = mPresShell->GetRootFrame();
}
if (frame) {
frame->HandleEvent(MOZ_KnownLive(aVisitor.mPresContext),
aVisitor.mEvent->AsGUIEvent(),
frame->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent->AsGUIEvent(),
&aVisitor.mEventStatus);
}
}

View File

@ -807,6 +807,7 @@
# define MOZ_MAY_CALL_AFTER_MUST_RETURN \
__attribute__((annotate("moz_may_call_after_must_return")))
# define MOZ_LIFETIME_BOUND __attribute__((annotate("moz_lifetime_bound")))
# define MOZ_KNOWN_LIVE __attribute__((annotate("moz_known_live")))
/*
* It turns out that clang doesn't like void func() __attribute__ {} without a
@ -860,6 +861,7 @@
# define MOZ_MUST_RETURN_FROM_CALLER_IF_THIS_IS_ARG /* nothing */
# define MOZ_MAY_CALL_AFTER_MUST_RETURN /* nothing */
# define MOZ_LIFETIME_BOUND /* nothing */
# define MOZ_KNOWN_LIVE /* nothing */
# endif /* defined(MOZ_CLANG_PLUGIN) || defined(XGILL_PLUGIN) */
# define MOZ_RAII MOZ_NON_TEMPORARY_CLASS MOZ_STACK_CLASS