Commit message: None
CVE: CVE-2018-17474
CWE: CWE-416
Vulnerability description: Use after free in HTMLImportsController in Blink in Google Chrome prior to 70.0.3538.67 allowed a remote attacker to potentially exploit heap corruption via a crafted HTML page.

Project: Chrome

HTMLImportChild* HTMLImportsController::CreateChild(
    const KURL& url,
    HTMLImportLoader* loader,
    HTMLImport* parent,
    HTMLImportChildClient* client) {
  HTMLImport::SyncMode mode = client->IsSync() && !MakesCycle(parent, url)
                                  ? HTMLImport::kSync
                                  : HTMLImport::kAsync;
  if (mode == HTMLImport::kAsync) {
    UseCounter::Count(root_->GetDocument(),
                      WebFeature::kHTMLImportsAsyncAttribute);
  }

  HTMLImportChild* child = new HTMLImportChild(url, loader, client, mode);
  parent->AppendImport(child);
  loader->AddImport(child);
  return root_->Add(child);
}

Project: Chrome

HTMLImportsController::HTMLImportsController(Document& master)
     : root_(HTMLImportTreeRoot::Create(&master)) {}

Project: Chrome

HTMLImportChild* HTMLImportsController::Load(const Document& parent_document,
                                             HTMLImportChildClient* client,
                                             FetchParameters& params) {
  DCHECK(client);

  HTMLImportLoader* parent_loader = LoaderFor(parent_document);
  HTMLImport* parent =
      parent_loader ? static_cast<HTMLImport*>(parent_loader->FirstImport())
                    : static_cast<HTMLImport*>(root_);

  const KURL& url = params.Url();

  DCHECK(!url.IsEmpty());
  DCHECK(url.IsValid());

  if (HTMLImportChild* child_to_share_with = root_->Find(url)) {
    HTMLImportLoader* loader = child_to_share_with->Loader();
    DCHECK(loader);
    HTMLImportChild* child = CreateChild(url, loader, parent, client);
    child->DidShareLoader();
    return child;
  }

  params.SetCrossOriginAccessControl(Master()->GetSecurityOrigin(),
                                     kCrossOriginAttributeAnonymous);

  HTMLImportLoader* loader = HTMLImportLoader::Create(this);
  ResourceFetcher* fetcher = parent->GetDocument()->Fetcher();
  RawResource::FetchImport(params, fetcher, loader);
  loaders_.push_back(loader);
  HTMLImportChild* child = CreateChild(url, loader, parent, client);
  child->DidStartLoading();
  return child;
}

Project: Chrome

HTMLImportLoader* HTMLImportsController::LoaderFor(
    const Document& document) const {
  for (const auto& loader : loaders_) {
    if (loader->GetDocument() == &document)
      return loader.Get();
  }

  return nullptr;
}

Project: Chrome

static bool MakesCycle(HTMLImport* parent, const KURL& url) {
  for (HTMLImport* ancestor = parent; ancestor; ancestor = ancestor->Parent()) {
    if (!ancestor->IsRoot() &&
        EqualIgnoringFragmentIdentifier(ToHTMLImportChild(parent)->Url(), url))
      return true;
  }

  return false;
}

Project: Chrome

bool HTMLImportsController::ShouldBlockScriptExecution(
    const Document& document) const {
  DCHECK_EQ(document.ImportsController(), this);
  if (HTMLImportLoader* loader = LoaderFor(document))
    return loader->ShouldBlockScriptExecution();
  return root_->GetState().ShouldBlockScriptExecution();
}

Project: Chrome

void HTMLImportsController::Trace(blink::Visitor* visitor) {
  visitor->Trace(root_);
  visitor->Trace(loaders_);
}