Title: [116642] trunk/Source/WebCore
Revision
116642
Author
[email protected]
Date
2012-05-10 07:11:37 -0700 (Thu, 10 May 2012)

Log Message

Crash in HTMLFormControlElement::m_fieldSetAncestor
https://bugs.webkit.org/show_bug.cgi?id=86070

Reviewed by Kent Tamura.

No new tests.

The previous patch r115990 didn't completely resolve the crash (Bug 85453)
We don't have a reproducible test case, so we are reverting to the old code for setting m_fieldSetAncestor.

* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::HTMLFormControlElement):
(WebCore::HTMLFormControlElement::updateFieldSetAndLegendAncestor):
(WebCore::HTMLFormControlElement::insertedInto): Set m_dataListAncestorState to Unknown because ancestor has changed. Call setNeedsWillValidateCheck because style might need to be updated.
(WebCore::HTMLFormControlElement::removedFrom):
(WebCore::HTMLFormControlElement::disabled):
(WebCore::HTMLFormControlElement::recalcWillValidate):
(WebCore::HTMLFormControlElement::willValidate):
(WebCore::HTMLFormControlElement::setNeedsWillValidateCheck):
* html/HTMLFormControlElement.h:
(HTMLFormControlElement): Added m_dataListAncestorState.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (116641 => 116642)


--- trunk/Source/WebCore/ChangeLog	2012-05-10 14:05:32 UTC (rev 116641)
+++ trunk/Source/WebCore/ChangeLog	2012-05-10 14:11:37 UTC (rev 116642)
@@ -1,3 +1,27 @@
+2012-05-10  Keishi Hattori  <[email protected]>
+
+        Crash in HTMLFormControlElement::m_fieldSetAncestor
+        https://bugs.webkit.org/show_bug.cgi?id=86070
+
+        Reviewed by Kent Tamura.
+
+        No new tests.
+
+        The previous patch r115990 didn't completely resolve the crash (Bug 85453)
+        We don't have a reproducible test case, so we are reverting to the old code for setting m_fieldSetAncestor.
+
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::HTMLFormControlElement):
+        (WebCore::HTMLFormControlElement::updateFieldSetAndLegendAncestor):
+        (WebCore::HTMLFormControlElement::insertedInto): Set m_dataListAncestorState to Unknown because ancestor has changed. Call setNeedsWillValidateCheck because style might need to be updated.
+        (WebCore::HTMLFormControlElement::removedFrom):
+        (WebCore::HTMLFormControlElement::disabled):
+        (WebCore::HTMLFormControlElement::recalcWillValidate):
+        (WebCore::HTMLFormControlElement::willValidate):
+        (WebCore::HTMLFormControlElement::setNeedsWillValidateCheck):
+        * html/HTMLFormControlElement.h:
+        (HTMLFormControlElement): Added m_dataListAncestorState.
+
 2012-05-10  Sam D  <[email protected]>
 
         Web Inspector: rename InspectorBackendStub.js to InspectorBackendCommands.js

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (116641 => 116642)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2012-05-10 14:05:32 UTC (rev 116641)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2012-05-10 14:11:37 UTC (rev 116642)
@@ -50,17 +50,17 @@
     : LabelableElement(tagName, document)
     , m_fieldSetAncestor(0)
     , m_legendAncestor(0)
-    , m_ancestorsValid(false)
+    , m_fieldSetAncestorValid(false)
     , m_disabled(false)
     , m_readOnly(false)
     , m_required(false)
     , m_valueMatchesRenderer(false)
+    , m_dataListAncestorState(Unknown)
     , m_willValidateInitialized(false)
     , m_willValidate(true)
     , m_isValid(true)
     , m_wasChangedSinceLastFormControlChangeEvent(false)
     , m_hasAutofocused(false)
-    , m_hasDataListAncestor(false)
 {
     setForm(form ? form : findFormAncestor());
     setHasCustomWillOrDidRecalcStyle();
@@ -101,22 +101,19 @@
     return fastHasAttribute(formnovalidateAttr);
 }
 
-void HTMLFormControlElement::updateAncestors() const
+void HTMLFormControlElement::updateFieldSetAndLegendAncestor() const
 {
     m_fieldSetAncestor = 0;
     m_legendAncestor = 0;
-    m_hasDataListAncestor = false;
     for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
         if (!m_legendAncestor && ancestor->hasTagName(legendTag))
             m_legendAncestor = static_cast<HTMLLegendElement*>(ancestor);
-        if (!m_fieldSetAncestor && ancestor->hasTagName(fieldsetTag))
+        if (ancestor->hasTagName(fieldsetTag)) {
             m_fieldSetAncestor = static_cast<HTMLFieldSetElement*>(ancestor);
-        if (!m_hasDataListAncestor && ancestor->hasTagName(datalistTag))
-            m_hasDataListAncestor = true;
-        if (m_hasDataListAncestor && m_fieldSetAncestor)
             break;
+        }
     }
-    m_ancestorsValid = true;
+    m_fieldSetAncestorValid = true;
 }
 
 void HTMLFormControlElement::parseAttribute(Attribute* attr)
@@ -227,18 +224,19 @@
 
 Node::InsertionNotificationRequest HTMLFormControlElement::insertedInto(Node* insertionPoint)
 {
+    m_dataListAncestorState = Unknown;
+    setNeedsWillValidateCheck();
     HTMLElement::insertedInto(insertionPoint);
     FormAssociatedElement::insertedInto(insertionPoint);
-    m_ancestorsValid = false;
-    setNeedsWillValidateCheck();
     return InsertionDone;
 }
 
 void HTMLFormControlElement::removedFrom(Node* insertionPoint)
 {
+    m_fieldSetAncestorValid = false;
+    m_dataListAncestorState = Unknown;
     HTMLElement::removedFrom(insertionPoint);
     FormAssociatedElement::removedFrom(insertionPoint);
-    m_ancestorsValid = false;
 }
 
 const AtomicString& HTMLFormControlElement::formControlName() const
@@ -279,8 +277,8 @@
     if (m_disabled)
         return true;
 
-    if (!m_ancestorsValid)
-        updateAncestors();
+    if (!m_fieldSetAncestorValid)
+        updateFieldSetAndLegendAncestor();
 
     // Form controls in the first legend element inside a fieldset are not affected by fieldset.disabled.
     if (m_fieldSetAncestor && m_fieldSetAncestor->disabled())
@@ -359,15 +357,22 @@
 
 bool HTMLFormControlElement::recalcWillValidate() const
 {
-    return !m_hasDataListAncestor && !m_disabled && !m_readOnly;
+    if (m_dataListAncestorState == Unknown) {
+        for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
+            if (!m_legendAncestor && ancestor->hasTagName(datalistTag)) {
+                m_dataListAncestorState = InsideDataList;
+                break;
+            }
+        }
+        if (m_dataListAncestorState == Unknown)
+            m_dataListAncestorState = NotInsideDataList;
+    }
+    return m_dataListAncestorState == NotInsideDataList && !m_disabled && !m_readOnly;
 }
 
 bool HTMLFormControlElement::willValidate() const
 {
-    if (!m_willValidateInitialized || !m_ancestorsValid) {
-        if (!m_ancestorsValid)
-            updateAncestors();
-
+    if (!m_willValidateInitialized || m_dataListAncestorState == Unknown) {
         m_willValidateInitialized = true;
         m_willValidate = recalcWillValidate();
     } else {
@@ -381,9 +386,6 @@
 
 void HTMLFormControlElement::setNeedsWillValidateCheck()
 {
-    if (!m_ancestorsValid)
-        updateAncestors();
-
     // We need to recalculate willValidate immediately because willValidate change can causes style change.
     bool newWillValidate = recalcWillValidate();
     if (m_willValidateInitialized && m_willValidate == newWillValidate)

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.h (116641 => 116642)


--- trunk/Source/WebCore/html/HTMLFormControlElement.h	2012-05-10 14:05:32 UTC (rev 116641)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.h	2012-05-10 14:11:37 UTC (rev 116642)
@@ -51,7 +51,7 @@
     void setFormMethod(const String&);
     bool formNoValidate() const;
 
-    void updateAncestors() const;
+    void updateFieldSetAndLegendAncestor() const;
 
     virtual void reset() { }
 
@@ -153,12 +153,15 @@
     mutable HTMLFieldSetElement* m_fieldSetAncestor;
     mutable HTMLLegendElement* m_legendAncestor;
     OwnPtr<ValidationMessage> m_validationMessage;
-    mutable bool m_ancestorsValid : 1;
+    mutable bool m_fieldSetAncestorValid : 1;
     bool m_disabled : 1;
     bool m_readOnly : 1;
     bool m_required : 1;
     bool m_valueMatchesRenderer : 1;
 
+    enum DataListAncestorState { Unknown, InsideDataList, NotInsideDataList };
+    mutable enum DataListAncestorState m_dataListAncestorState;
+
     // The initial value of m_willValidate depends on the derived class. We can't
     // initialize it with a virtual function in the constructor. m_willValidate
     // is not deterministic as long as m_willValidateInitialized is false.
@@ -172,7 +175,6 @@
     bool m_wasChangedSinceLastFormControlChangeEvent : 1;
 
     bool m_hasAutofocused : 1;
-    mutable bool m_hasDataListAncestor : 1;
 };
 
 } // namespace
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to