From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rune Lillesveen <futhark@chromium.org>
Date: Thu, 24 Aug 2023 10:53:36 +0000
Subject: Don't keep pointer to popped stack memory for :has()

The sibling_features pass into UpdateFeaturesFromCombinator may be
initialized to last_compound_in_adjacent_chain_features if null. The
outer while loop in
AddFeaturesToInvalidationSetsForLogicalCombinationInHas() could then
reference to the last_compound_in_adjacent_chain_features which is
popped from the stack on every outer iteration. That caused an ASAN
failure for reading stack memory that had been popped.

Instead make sure each inner iteration restarts with the same
sibling_features pointer, which seems to have been the intent here.

(cherry picked from commit 5e213507a2f0d6e3c96904a710407b01493670bd)

Bug: 1470477
Change-Id: I260c93016f8ab0d165e4b29ca1aea810bede5b97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4759326
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1181365}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4777251
Cr-Commit-Position: refs/branch-heads/5845@{#1482}
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
(cherry picked from commit 34e544e4dedf299211f104a2822d98ce1db80f61)

diff --git a/third_party/blink/renderer/core/css/rule_feature_set.cc b/third_party/blink/renderer/core/css/rule_feature_set.cc
index 35483b54816197b3244cac4bb32759a88de57664..c6a93968829a8dc6d14247e8882a9a3fdcfb6f84 100644
--- a/third_party/blink/renderer/core/css/rule_feature_set.cc
+++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -1322,6 +1322,7 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
         descendant_features);
 
     const CSSSelector* compound_in_logical_combination = complex;
+    InvalidationSetFeatures* inner_sibling_features = sibling_features;
     InvalidationSetFeatures last_compound_in_adjacent_chain_features;
     while (compound_in_logical_combination) {
       AddFeaturesToInvalidationSetsForLogicalCombinationInHasContext context(
@@ -1333,14 +1334,14 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
         last_in_compound =
             SkipAddingAndGetLastInCompoundForLogicalCombinationInHas(
                 compound_in_logical_combination, compound_containing_has,
-                sibling_features, descendant_features, previous_combinator,
-                add_features_method);
+                inner_sibling_features, descendant_features,
+                previous_combinator, add_features_method);
       } else {
         last_in_compound =
             AddFeaturesAndGetLastInCompoundForLogicalCombinationInHas(
                 compound_in_logical_combination, compound_containing_has,
-                sibling_features, descendant_features, previous_combinator,
-                add_features_method);
+                inner_sibling_features, descendant_features,
+                previous_combinator, add_features_method);
       }
 
       if (!last_in_compound) {
@@ -1355,7 +1356,7 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
                 ? CSSSelector::kIndirectAdjacent
                 : previous_combinator,
             context.last_compound_in_adjacent_chain,
-            last_compound_in_adjacent_chain_features, sibling_features,
+            last_compound_in_adjacent_chain_features, inner_sibling_features,
             descendant_features);
       }
 
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html
new file mode 100644
index 0000000000000000000000000000000000000000..0306e3e39272c321fc3539aa582b4e239ffe2fa1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>CSS Selectors Test: Chrome crash issue 1470477</title>
+<link rel="help" href="https://crbug.com/1470477">
+<style>
+  :has(> :where(label:first-child + [a="a"]:only-of-type,
+    [a="a"]:only-of-type + label:last-child)) label:last-child {
+      margin-inline: 1em;
+  }
+</style>
+<p>PASS if this tests does not crash</p>
