diff --git a/build/clang-plugin/CanRunScriptChecker.cpp b/build/clang-plugin/CanRunScriptChecker.cpp index f75f0380e001..3c531da41783 100644 --- a/build/clang-plugin/CanRunScriptChecker.cpp +++ b/build/clang-plugin/CanRunScriptChecker.cpp @@ -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())))); diff --git a/build/clang-plugin/CustomAttributes.inc b/build/clang-plugin/CustomAttributes.inc index 2986ab9e4a42..78e09d83575e 100644 --- a/build/clang-plugin/CustomAttributes.inc +++ b/build/clang-plugin/CustomAttributes.inc @@ -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) diff --git a/build/clang-plugin/CustomMatchers.h b/build/clang-plugin/CustomMatchers.h index 54bb0d02dd2e..04dbe60f7f06 100644 --- a/build/clang-plugin/CustomMatchers.h +++ b/build/clang-plugin/CustomMatchers.h @@ -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(Member); + return Field && hasCustomAttribute(Field); +} + } // namespace ast_matchers } // namespace clang diff --git a/build/clang-plugin/tests/TestCanRunScript.cpp b/build/clang-plugin/tests/TestCanRunScript.cpp index 01ca514f6c4f..1026c612727f 100644 --- a/build/clang-plugin/tests/TestCanRunScript.cpp +++ b/build/clang-plugin/tests/TestCanRunScript.cpp @@ -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.}} + } +}; diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 99ec6683c2d8..f0fa048adee8 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -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; } diff --git a/dom/events/EventDispatcher.h b/dom/events/EventDispatcher.h index 031c34202678..0736ed6891e3 100644 --- a/dom/events/EventDispatcher.h +++ b/dom/events/EventDispatcher.h @@ -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) {} }; diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index 085ae90ee9dd..8503422bea72 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -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); } } diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 21677721bb06..038041661fc2 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -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); } } diff --git a/dom/html/HTMLLabelElement.cpp b/dom/html/HTMLLabelElement.cpp index 9222b58a9761..55ea679586e1 100644 --- a/dom/html/HTMLLabelElement.cpp +++ b/dom/html/HTMLLabelElement.cpp @@ -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