diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 081fc5337cf2..17dd97449259 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -3455,7 +3455,23 @@ nsresult Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor) { return rv; } -void Element::GetLinkTarget(nsAString& aTarget) { aTarget.Truncate(); } +// static +void Element::SanitizeLinkOrFormTarget(nsAString& aTarget) { + // + // 2. If target is not null, and contains an ASCII tab or newline and a U+003C + // (<), then set target to "_blank". + if (!aTarget.IsEmpty() && aTarget.FindCharInSet(u"\t\n\r") != kNotFound && + aTarget.Contains('<')) { + aTarget.AssignLiteral("_blank"); + } +} + +void Element::GetLinkTarget(nsAString& aTarget) { + GetLinkTargetImpl(aTarget); + SanitizeLinkOrFormTarget(aTarget); +} + +void Element::GetLinkTargetImpl(nsAString& aTarget) { aTarget.Truncate(); } nsresult Element::CopyInnerTo(Element* aDst, ReparseAttributes aReparse) { nsresult rv = aDst->mAttrs.EnsureCapacityToClone(mAttrs); diff --git a/dom/base/Element.h b/dom/base/Element.h index 3d3ddc213c4a..f734c41d5bdd 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -2122,17 +2122,29 @@ class Element : public FragmentOrElement { */ virtual already_AddRefed GetHrefURI() const { return nullptr; } + // Step 2. of + // + // + // Sanitize targets that look like they contain dangling markup. + static void SanitizeLinkOrFormTarget(nsAString& aTarget); + /** + * + * (Excluding
) + * * Get the target of this link element. Consumers should established that * this element is a link (probably using IsLink) before calling this - * function (or else why call it?) + * function (or else why call it?). This method neuters probably markup + * injection attempts. * * Note: for HTML this gets the value of the 'target' attribute; for XLink * this gets the value of the xlink:_moz_target attribute, or failing that, * the value of xlink:show, converted to a suitably equivalent named target * (e.g. _blank). */ - virtual void GetLinkTarget(nsAString& aTarget); + void GetLinkTarget(nsAString& aTarget); + + virtual void GetLinkTargetImpl(nsAString& aTarget); virtual bool Translate() const; diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp index 8c1689fe7d3a..c52ebad067ab 100644 --- a/dom/html/HTMLAnchorElement.cpp +++ b/dom/html/HTMLAnchorElement.cpp @@ -134,7 +134,7 @@ nsresult HTMLAnchorElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { return PostHandleEventForAnchors(aVisitor); } -void HTMLAnchorElement::GetLinkTarget(nsAString& aTarget) { +void HTMLAnchorElement::GetLinkTargetImpl(nsAString& aTarget) { GetAttr(nsGkAtoms::target, aTarget); if (aTarget.IsEmpty()) { GetBaseTarget(aTarget); diff --git a/dom/html/HTMLAnchorElement.h b/dom/html/HTMLAnchorElement.h index f7f808de05a7..9c30cf144a87 100644 --- a/dom/html/HTMLAnchorElement.h +++ b/dom/html/HTMLAnchorElement.h @@ -55,7 +55,7 @@ class HTMLAnchorElement final : public nsGenericHTMLElement, MOZ_CAN_RUN_SCRIPT nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; - void GetLinkTarget(nsAString& aTarget) override; + void GetLinkTargetImpl(nsAString& aTarget) override; already_AddRefed GetHrefURI() const override; void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, diff --git a/dom/html/HTMLAreaElement.cpp b/dom/html/HTMLAreaElement.cpp index fc47069ead0d..7eb4468c1234 100644 --- a/dom/html/HTMLAreaElement.cpp +++ b/dom/html/HTMLAreaElement.cpp @@ -49,7 +49,7 @@ nsresult HTMLAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { return PostHandleEventForAnchors(aVisitor); } -void HTMLAreaElement::GetLinkTarget(nsAString& aTarget) { +void HTMLAreaElement::GetLinkTargetImpl(nsAString& aTarget) { GetAttr(nsGkAtoms::target, aTarget); if (aTarget.IsEmpty()) { GetBaseTarget(aTarget); diff --git a/dom/html/HTMLAreaElement.h b/dom/html/HTMLAreaElement.h index 6e9744ae624f..8c003df17b9f 100644 --- a/dom/html/HTMLAreaElement.h +++ b/dom/html/HTMLAreaElement.h @@ -39,7 +39,7 @@ class HTMLAreaElement final : public nsGenericHTMLElement, public Link { MOZ_CAN_RUN_SCRIPT nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; - void GetLinkTarget(nsAString& aTarget) override; + void GetLinkTargetImpl(nsAString& aTarget) override; already_AddRefed GetHrefURI() const override; virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index 7796c4b1f483..592cba84c095 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -1671,6 +1671,22 @@ nsresult HTMLFormElement::GetActionURL(nsIURI** aActionURL, return rv; } +void HTMLFormElement::GetSubmissionTarget(nsGenericHTMLElement* aSubmitter, + nsAString& aTarget) { + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm + // 19. If the submitter element is a submit button and it has a formtarget + // attribute, then set formTarget to the formtarget attribute value. + // 20. Let target be the result of getting an element's target given + // submitter's form owner and formTarget. + // + // Note: Falling back to the base target is part of "get an element's target". + if (!(aSubmitter && aSubmitter->GetAttr(nsGkAtoms::formtarget, aTarget)) && + !GetAttr(nsGkAtoms::target, aTarget)) { + GetBaseTarget(aTarget); + } + SanitizeLinkOrFormTarget(aTarget); +} + nsGenericHTMLFormElement* HTMLFormElement::GetDefaultSubmitElement() const { MOZ_ASSERT(mDefaultSubmitElement == mFirstSubmitInElements || mDefaultSubmitElement == mFirstSubmitNotInElements, diff --git a/dom/html/HTMLFormElement.h b/dom/html/HTMLFormElement.h index 263f665843d7..4cd3a3ca1e71 100644 --- a/dom/html/HTMLFormElement.h +++ b/dom/html/HTMLFormElement.h @@ -481,6 +481,11 @@ class HTMLFormElement final : public nsGenericHTMLElement { */ nsresult GetActionURL(nsIURI** aActionURL, Element* aOriginatingElement); + // Get the target to submit to. This is either the submitter's |formtarget| or + // the form's |target| (Including ). + void GetSubmissionTarget(nsGenericHTMLElement* aSubmitter, + nsAString& aTarget); + // Returns a number for this form that is unique within its owner document. // This is used by nsContentUtils::GenerateStateKey to identify form controls // that are inserted into the document by the parser. diff --git a/dom/html/HTMLFormSubmission.cpp b/dom/html/HTMLFormSubmission.cpp index fa25794274ac..8d6eeb98211e 100644 --- a/dom/html/HTMLFormSubmission.cpp +++ b/dom/html/HTMLFormSubmission.cpp @@ -828,18 +828,8 @@ nsresult HTMLFormSubmission::GetFromForm(HTMLFormElement* aForm, } // Get target - // The target is the submitter element formtarget attribute if the element - // is a submit control and has such an attribute. - // Otherwise, the target is the form owner's target attribute, - // if it has such an attribute. - // Finally, if one of the child nodes of the head element is a base element - // with a target attribute, then the value of the target attribute of the - // first such base element; or, if there is no such element, the empty string. nsAutoString target; - if (!(aSubmitter && aSubmitter->GetAttr(nsGkAtoms::formtarget, target)) && - !aForm->GetAttr(nsGkAtoms::target, target)) { - aForm->GetBaseTarget(target); - } + aForm->GetSubmissionTarget(aSubmitter, target); // Get encoding type (default: urlencoded) int32_t enctype = NS_FORM_ENCTYPE_URLENCODED; diff --git a/dom/svg/SVGAElement.cpp b/dom/svg/SVGAElement.cpp index bffc3d1a98db..b7ffbb624a69 100644 --- a/dom/svg/SVGAElement.cpp +++ b/dom/svg/SVGAElement.cpp @@ -210,7 +210,7 @@ already_AddRefed SVGAElement::GetHrefURI() const { return nullptr; } -void SVGAElement::GetLinkTarget(nsAString& aTarget) { +void SVGAElement::GetLinkTargetImpl(nsAString& aTarget) { mStringAttributes[TARGET].GetAnimValue(aTarget, this); if (aTarget.IsEmpty()) { static Element::AttrValuesArray sShowVals[] = {nsGkAtoms::_new, diff --git a/dom/svg/SVGAElement.h b/dom/svg/SVGAElement.h index 5e476c033cb5..38ed7b597a51 100644 --- a/dom/svg/SVGAElement.h +++ b/dom/svg/SVGAElement.h @@ -52,7 +52,7 @@ class SVGAElement final : public SVGAElementBase, public Link { int32_t TabIndexDefault() override; Focusable IsFocusableWithoutStyle(IsFocusableFlags) override; - void GetLinkTarget(nsAString& aTarget) override; + void GetLinkTargetImpl(nsAString& aTarget) override; already_AddRefed GetHrefURI() const override; bool HasHref() const; diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 2ab0da086b6f..832c9fef9cbc 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1050,9 +1050,8 @@ bool nsImageFrame::ShouldCreateImageFrameForContentProperty( // Check if we want to use an image frame or just let the frame constructor make // us into an inline, and if so, which kind of image frame should we create. /* static */ -auto nsImageFrame::ImageFrameTypeFor(const Element& aElement, - const ComputedStyle& aStyle) - -> ImageFrameType { +auto nsImageFrame::ImageFrameTypeFor( + const Element& aElement, const ComputedStyle& aStyle) -> ImageFrameType { if (ShouldCreateImageFrameForContentProperty(aElement, aStyle)) { // Prefer the content property, for compat reasons, see bug 1484928. return ImageFrameType::ForContentProperty; @@ -2617,7 +2616,7 @@ bool nsImageFrame::GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget, } if (auto* anchor = HTMLAnchorElement::FromNode(content)) { - anchor->GetTarget(aTarget); + anchor->GetLinkTarget(aTarget); } NS_ADDREF(*aNode = content); return *aHref != nullptr; diff --git a/testing/web-platform/meta/html/browsers/windows/dangling-markup-window-name.html.ini b/testing/web-platform/meta/html/browsers/windows/dangling-markup-window-name.html.ini deleted file mode 100644 index e9e6aaa53bff..000000000000 --- a/testing/web-platform/meta/html/browsers/windows/dangling-markup-window-name.html.ini +++ /dev/null @@ -1,15 +0,0 @@ -[dangling-markup-window-name.html] - [Dangling Markup with "\\n" in target is reset when set by tag] - expected: FAIL - - [Dangling Markup with "\\r" in target is reset when set by tag] - expected: FAIL - - [Dangling Markup with "\\t" in target is reset when set by tag] - expected: FAIL - - [Dangling Markup in target is reset when set by tag] - expected: FAIL - - [Dangling Markup in target is reset when set by tag] - expected: FAIL