Commit message: None
CVE: CVE-2019-5757
CWE: CWE-704
Vulnerability description: An incorrect object type assumption in SVG in Google Chrome prior to 72.0.3626.81 allowed a remote attacker to potentially exploit object corruption via a crafted HTML page.

Project: Chrome

void SVGElement::AddedEventListener(
    const AtomicString& event_type,
    RegisteredEventListener& registered_listener) {
  Node::AddedEventListener(event_type, registered_listener);

  HeapHashSet<WeakMember<SVGElement>> instances;
  CollectInstancesForSVGElement(this, instances);
  AddEventListenerOptionsResolved* options = registered_listener.Options();
  EventListener* listener = registered_listener.Callback();
  for (SVGElement* element : instances) {
    bool result =
        element->Node::AddEventListenerInternal(event_type, listener, options);
    DCHECK(result);
  }
}

Project: Chrome

void SVGElement::AttachLayoutTree(AttachContext& context) {
  Element::AttachLayoutTree(context);
  if (SVGElement* element = CorrespondingElement())
    element->MapInstanceToElement(this);
}

Project: Chrome

AffineTransform SVGElement::CalculateTransform(
    ApplyMotionTransform apply_motion_transform) const {
  const ComputedStyle* style =
      GetLayoutObject() ? GetLayoutObject()->Style() : nullptr;

  AffineTransform matrix;
  if (style && style->HasTransform()) {
    FloatRect reference_box = ComputeTransformReferenceBox(*this);
    if (TransformUsesBoxSize(*style))
      UseCounter::Count(GetDocument(), WebFeature::kTransformUsesBoxSizeOnSVG);

    float zoom = style->EffectiveZoom();
    TransformationMatrix transform;
    if (zoom != 1)
      reference_box.Scale(zoom);
    style->ApplyTransform(
        transform, reference_box, ComputedStyle::kIncludeTransformOrigin,
        ComputedStyle::kIncludeMotionPath,
        ComputedStyle::kIncludeIndependentTransformProperties);
    if (zoom != 1)
      transform.Zoom(1 / zoom);
    matrix = transform.ToAffineTransform();
  }

  if (apply_motion_transform == kIncludeMotionTransform && HasSVGRareData())
    matrix.PreMultiply(*SvgRareData()->AnimateMotionTransform());

  return matrix;
}

Project: Chrome

void SVGElement::ClearAnimatedAttribute(const QualifiedName& attribute) {
  ForSelfAndInstances(this, [&attribute](SVGElement* element) {
    if (SVGAnimatedPropertyBase* animated_property =
            element->PropertyFromAttribute(attribute))
      animated_property->AnimationEnded();
  });
}

Project: Chrome

SVGResourceClient& SVGElement::EnsureSVGResourceClient() {
  return EnsureSVGRareData()->EnsureSVGResourceClient(this);
}

Project: Chrome

static bool HasLoadListener(Element* element) {
  if (element->HasEventListeners(event_type_names::kLoad))
    return true;

  for (element = element->ParentOrShadowHostElement(); element;
       element = element->ParentOrShadowHostElement()) {
    EventListenerVector* entry =
        element->GetEventListeners(event_type_names::kLoad);
    if (!entry)
      continue;
    for (wtf_size_t i = 0; i < entry->size(); ++i) {
      if (entry->at(i).Capture())
        return true;
    }
  }

  return false;
}

Project: Chrome

bool SVGElement::HaveLoadedRequiredResources() {
  for (SVGElement* child = Traversal<SVGElement>::FirstChild(*this); child;
       child = Traversal<SVGElement>::NextSibling(*child)) {
    if (!child->HaveLoadedRequiredResources())
      return false;
  }
  return true;
}

Project: Chrome

Node::InsertionNotificationRequest SVGElement::InsertedInto(
    ContainerNode& root_parent) {
  Element::InsertedInto(root_parent);
  UpdateRelativeLengthsInformation();

  const AtomicString& nonce_value = FastGetAttribute(kNonceAttr);
  if (!nonce_value.IsEmpty()) {
    setNonce(nonce_value);
    if (InActiveDocument() &&
        GetDocument().GetContentSecurityPolicy()->HasHeaderDeliveredPolicy()) {
      setAttribute(kNonceAttr, g_empty_atom);
    }
  }
  return kInsertionDone;
}

Project: Chrome

bool SVGElement::IsPresentationAttributeWithSVGDOM(
    const QualifiedName& name) const {
  const SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
  return property && property->HasPresentationAttributeMapping();
}

Project: Chrome

void SVGElement::ParseAttribute(const AttributeModificationParams& params) {
  if (SVGAnimatedPropertyBase* property = PropertyFromAttribute(params.name)) {
    SVGParsingError parse_error = property->AttributeChanged(params.new_value);
    ReportAttributeParsingError(parse_error, params.name, params.new_value);
    return;
  }

  const AtomicString& event_name =
      HTMLElement::EventNameForAttributeName(params.name);
  if (!event_name.IsNull()) {
    SetAttributeEventListener(
        event_name,
        CreateAttributeEventListener(this, params.name, params.new_value));
    return;
  }

  Element::ParseAttribute(params);
}

Project: Chrome

static inline bool TransformUsesBoxSize(const ComputedStyle& style) {
  if ((style.TransformOriginX().IsPercent() ||
       style.TransformOriginY().IsPercent()) &&
      style.RequireTransformOrigin(ComputedStyle::kIncludeTransformOrigin,
                                   ComputedStyle::kExcludeMotionPath))
    return true;
  if (style.Transform().DependsOnBoxSize())
    return true;
  if (style.Translate() && style.Translate()->DependsOnBoxSize())
    return true;
  if (style.HasOffset())
    return true;
  return false;
}

Project: Chrome

void SVGElement::UpdateRelativeLengthsInformation(
    bool client_has_relative_lengths,
    SVGElement* client_element) {
  DCHECK(client_element);

  for (Node& current_node : NodeTraversal::InclusiveAncestorsOf(*this)) {
    if (!current_node.isConnected())
      return;
  }

  for (Node& current_node : NodeTraversal::InclusiveAncestorsOf(*this)) {
    if (!current_node.IsSVGElement())
      break;
    SVGElement& current_element = ToSVGElement(current_node);
#if DCHECK_IS_ON()
    DCHECK(!current_element.in_relative_length_clients_invalidation_);
#endif

    bool had_relative_lengths = current_element.HasRelativeLengths();
    if (client_has_relative_lengths)
      current_element.elements_with_relative_lengths_.insert(client_element);
    else
      current_element.elements_with_relative_lengths_.erase(client_element);

    if (had_relative_lengths == current_element.HasRelativeLengths())
      return;

    client_element = &current_element;
    client_has_relative_lengths = client_element->HasRelativeLengths();
  }

  if (auto* svg = ToSVGSVGElementOrNull(*client_element)) {
    SVGDocumentExtensions& svg_extensions = GetDocument().AccessSVGExtensions();
    if (client_element->HasRelativeLengths())
      svg_extensions.AddSVGRootWithRelativeLengthDescendents(svg);
    else
      svg_extensions.RemoveSVGRootWithRelativeLengthDescendents(svg);
  }
}