Title: [283470] trunk/Source
Revision
283470
Author
[email protected]
Date
2021-10-03 10:22:24 -0700 (Sun, 03 Oct 2021)

Log Message

WebCore::Length incorrectly uses memcpy() for copy constructors/operator and IPC encoding/decoding
https://bugs.webkit.org/show_bug.cgi?id=230744

Reviewed by David Kilzer.
Source/WebCore:

Copy-constructing Length by memcpy is sketchy; replace with code that initializes the appropriate
fields based on type, taking care to deref() and ref() the calc handle.

Expose isFloat() for encoding.

* css/parser/CSSPropertyParserHelpers.cpp:
(WebCore::CSSPropertyParserHelpers::CalcParser::consumeValueIfCategory): Add a bit of calc logging.
* platform/Length.cpp:
(WebCore::Length::Length):
* platform/Length.h:
(WebCore::Length::Length):
(WebCore::Length::operator=):
(WebCore::Length::isFloat const):

Source/WebKit:

Safe encoding/decoding of Length requires that we encode the enum and fields separately,
and don't allow calc types (there isn't enough context in the receiving process to resolve
calc).

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<Length>::encode):
(IPC::ArgumentCoder<Length>::decode):
* Shared/WebCoreArgumentCoders.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (283469 => 283470)


--- trunk/Source/WebCore/ChangeLog	2021-10-03 17:19:59 UTC (rev 283469)
+++ trunk/Source/WebCore/ChangeLog	2021-10-03 17:22:24 UTC (rev 283470)
@@ -1,3 +1,24 @@
+2021-10-03  Simon Fraser  <[email protected]>
+
+        WebCore::Length incorrectly uses memcpy() for copy constructors/operator and IPC encoding/decoding
+        https://bugs.webkit.org/show_bug.cgi?id=230744
+
+        Reviewed by David Kilzer.
+
+        Copy-constructing Length by memcpy is sketchy; replace with code that initializes the appropriate
+        fields based on type, taking care to deref() and ref() the calc handle.
+        
+        Expose isFloat() for encoding.
+
+        * css/parser/CSSPropertyParserHelpers.cpp:
+        (WebCore::CSSPropertyParserHelpers::CalcParser::consumeValueIfCategory): Add a bit of calc logging.
+        * platform/Length.cpp:
+        (WebCore::Length::Length):
+        * platform/Length.h:
+        (WebCore::Length::Length):
+        (WebCore::Length::operator=):
+        (WebCore::Length::isFloat const):
+
 2021-10-03  Basuke Suzuki  <[email protected]>
 
         Enable release log to stderr

Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (283469 => 283470)


--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp	2021-10-03 17:19:59 UTC (rev 283469)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp	2021-10-03 17:22:24 UTC (rev 283470)
@@ -45,6 +45,7 @@
 #include "CalculationCategory.h"
 #include "ColorConversion.h"
 #include "ColorLuminance.h"
+#include "Logging.h"
 #include "Pair.h"
 #include "RenderStyleConstants.h"
 #include "RuntimeEnabledFeatures.h"
@@ -52,6 +53,7 @@
 #include "WebKitFontFamilyNames.h"
 #include <wtf/SortedArrayMap.h>
 #include <wtf/text/StringConcatenateNumbers.h>
+#include <wtf/text/TextStream.h>
 
 namespace WebCore {
 
@@ -142,8 +144,13 @@
 
     RefPtr<CSSPrimitiveValue> consumeValueIfCategory(CalculationCategory category)
     {
-        if (!m_calcValue || m_calcValue->category() != category)
+        if (!m_calcValue)
             return nullptr;
+
+        if (m_calcValue->category() != category) {
+            LOG_WITH_STREAM(Calc, stream << "CalcParser::consumeValueIfCategory - failing because calc category " << m_calcValue->category() << " does not match requested category " << category);
+            return nullptr;
+        }
         m_sourceRange = m_range;
         return m_pool.createValue(WTFMove(m_calcValue));
     }

Modified: trunk/Source/WebCore/platform/Length.cpp (283469 => 283470)


--- trunk/Source/WebCore/platform/Length.cpp	2021-10-03 17:19:59 UTC (rev 283469)
+++ trunk/Source/WebCore/platform/Length.cpp	2021-10-03 17:22:24 UTC (rev 283470)
@@ -243,9 +243,7 @@
 }
 
 Length::Length(Ref<CalculationValue>&& value)
-    : m_hasQuirk(false)
-    , m_type(LengthType::Calculated)
-    , m_isFloat(false)
+    : m_type(LengthType::Calculated)
 {
     m_calculationValueHandle = calculationValues().insert(WTFMove(value));
 }

Modified: trunk/Source/WebCore/platform/Length.h (283469 => 283470)


--- trunk/Source/WebCore/platform/Length.h	2021-10-03 17:19:59 UTC (rev 283469)
+++ trunk/Source/WebCore/platform/Length.h	2021-10-03 17:22:24 UTC (rev 283470)
@@ -23,7 +23,6 @@
 #pragma once
 
 #include "AnimationUtilities.h"
-#include <memory>
 #include <string.h>
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
@@ -37,9 +36,16 @@
 namespace WebCore {
 
 enum class LengthType : uint8_t {
-    Auto, Relative, Percent, Fixed,
-    Intrinsic, MinIntrinsic,
-    MinContent, MaxContent, FillAvailable, FitContent,
+    Auto,
+    Relative,
+    Percent,
+    Fixed,
+    Intrinsic,
+    MinIntrinsic,
+    MinContent,
+    MaxContent,
+    FillAvailable,
+    FitContent,
     Calculated,
     Undefined
 };
@@ -76,8 +82,6 @@
     void setValue(LengthType, LayoutUnit value);
     Length& operator*=(float);
 
-    void setHasQuirk(bool);
-
     bool operator==(const Length&) const;
     bool operator!=(const Length&) const;
 
@@ -101,6 +105,7 @@
     bool isMinIntrinsic() const;
 
     bool hasQuirk() const;
+    void setHasQuirk(bool);
 
     // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length
     // always contains a percentage, and without a maxValue passed to these functions
@@ -110,6 +115,8 @@
     bool isPositive() const;
     bool isNegative() const;
 
+    bool isFloat() const;
+
     bool isPercentOrCalculated() const; // Returns true for both Percent and Calculated.
 
     bool isIntrinsic() const;
@@ -124,17 +131,20 @@
 private:
     bool isCalculatedEqual(const Length&) const;
 
+    void initialize(const Length&);
+    void initialize(Length&&);
+
     WEBCORE_EXPORT void ref() const;
     WEBCORE_EXPORT void deref() const;
     
     union {
-        int m_intValue;
+        int m_intValue { 0 };
         float m_floatValue;
         unsigned m_calculationValueHandle;
     };
-    bool m_hasQuirk;
     LengthType m_type;
-    bool m_isFloat;
+    bool m_hasQuirk { false };
+    bool m_isFloat { false };
 };
 
 // Blend two lengths to produce a new length that is in between them. Used for animation.
@@ -145,31 +155,42 @@
 UniqueArray<Length> newLengthArray(const String&, int& length);
 
 inline Length::Length(LengthType type)
-    : m_intValue(0), m_hasQuirk(false), m_type(type), m_isFloat(false)
+    : m_type(type)
 {
     ASSERT(type != LengthType::Calculated);
 }
 
 inline Length::Length(int value, LengthType type, bool hasQuirk)
-    : m_intValue(value), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(false)
+    : m_intValue(value)
+    , m_type(type)
+    , m_hasQuirk(hasQuirk)
 {
     ASSERT(type != LengthType::Calculated);
 }
 
 inline Length::Length(LayoutUnit value, LengthType type, bool hasQuirk)
-    : m_floatValue(value.toFloat()), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
+    : m_floatValue(value.toFloat())
+    , m_type(type)
+    , m_hasQuirk(hasQuirk)
+    , m_isFloat(true)
 {
     ASSERT(type != LengthType::Calculated);
 }
 
 inline Length::Length(float value, LengthType type, bool hasQuirk)
-    : m_floatValue(value), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
+    : m_floatValue(value)
+    , m_type(type)
+    , m_hasQuirk(hasQuirk)
+    , m_isFloat(true)
 {
     ASSERT(type != LengthType::Calculated);
 }
 
 inline Length::Length(double value, LengthType type, bool hasQuirk)
-    : m_floatValue(static_cast<float>(value)), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
+    : m_floatValue(static_cast<float>(value))
+    , m_type(type)
+    , m_hasQuirk(hasQuirk)
+    , m_isFloat(true)
 {
     ASSERT(type != LengthType::Calculated);
 }
@@ -176,16 +197,12 @@
 
 inline Length::Length(const Length& other)
 {
-    if (other.isCalculated())
-        other.ref();
-
-    memcpy(static_cast<void*>(this), static_cast<void*>(const_cast<Length*>(&other)), sizeof(Length));
+    initialize(other);
 }
 
 inline Length::Length(Length&& other)
 {
-    memcpy(static_cast<void*>(this), static_cast<void*>(&other), sizeof(Length));
-    other.m_type = LengthType::Auto;
+    initialize(WTFMove(other));
 }
 
 inline Length& Length::operator=(const Length& other)
@@ -193,12 +210,10 @@
     if (this == &other)
         return *this;
 
-    if (other.isCalculated())
-        other.ref();
     if (isCalculated())
         deref();
 
-    memcpy(static_cast<void*>(this), static_cast<void*>(const_cast<Length*>(&other)), sizeof(Length));
+    initialize(other);
     return *this;
 }
 
@@ -210,11 +225,75 @@
     if (isCalculated())
         deref();
 
-    memcpy(static_cast<void*>(this), static_cast<void*>(&other), sizeof(Length));
-    other.m_type = LengthType::Auto;
+    initialize(WTFMove(other));
     return *this;
 }
 
+inline void Length::initialize(const Length& other)
+{
+    m_type = other.m_type;
+    m_hasQuirk = other.m_hasQuirk;
+
+    switch (m_type) {
+    case LengthType::Auto:
+    case LengthType::Undefined:
+        m_intValue = 0;
+        break;
+    case LengthType::Fixed:
+    case LengthType::Relative:
+    case LengthType::Intrinsic:
+    case LengthType::MinIntrinsic:
+    case LengthType::MinContent:
+    case LengthType::MaxContent:
+    case LengthType::FillAvailable:
+    case LengthType::FitContent:
+    case LengthType::Percent:
+        m_isFloat = other.m_isFloat;
+        if (m_isFloat)
+            m_floatValue = other.m_floatValue;
+        else
+            m_intValue = other.m_intValue;
+        break;
+    case LengthType::Calculated:
+        m_calculationValueHandle = other.m_calculationValueHandle;
+        ref();
+        break;
+    }
+}
+
+inline void Length::initialize(Length&& other)
+{
+    m_type = other.m_type;
+    m_hasQuirk = other.m_hasQuirk;
+
+    switch (m_type) {
+    case LengthType::Auto:
+    case LengthType::Undefined:
+        m_intValue = 0;
+        break;
+    case LengthType::Fixed:
+    case LengthType::Relative:
+    case LengthType::Intrinsic:
+    case LengthType::MinIntrinsic:
+    case LengthType::MinContent:
+    case LengthType::MaxContent:
+    case LengthType::FillAvailable:
+    case LengthType::FitContent:
+    case LengthType::Percent:
+        m_isFloat = other.m_isFloat;
+        if (m_isFloat)
+            m_floatValue = other.m_floatValue;
+        else
+            m_intValue = other.m_intValue;
+        break;
+    case LengthType::Calculated:
+        m_calculationValueHandle = std::exchange(other.m_calculationValueHandle, 0);
+        break;
+    }
+
+    other.m_type = LengthType::Auto;
+}
+
 inline Length::~Length()
 {
     if (isCalculated())
@@ -285,6 +364,11 @@
     return m_hasQuirk;
 }
 
+inline bool Length::isFloat() const
+{
+    return m_isFloat;
+}
+
 inline void Length::setHasQuirk(bool hasQuirk)
 {
     m_hasQuirk = hasQuirk;

Modified: trunk/Source/WebKit/ChangeLog (283469 => 283470)


--- trunk/Source/WebKit/ChangeLog	2021-10-03 17:19:59 UTC (rev 283469)
+++ trunk/Source/WebKit/ChangeLog	2021-10-03 17:22:24 UTC (rev 283470)
@@ -1,3 +1,19 @@
+2021-10-03  Simon Fraser  <[email protected]>
+
+        WebCore::Length incorrectly uses memcpy() for copy constructors/operator and IPC encoding/decoding
+        https://bugs.webkit.org/show_bug.cgi?id=230744
+
+        Reviewed by David Kilzer.
+        
+        Safe encoding/decoding of Length requires that we encode the enum and fields separately,
+        and don't allow calc types (there isn't enough context in the receiving process to resolve
+        calc).
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<Length>::encode):
+        (IPC::ArgumentCoder<Length>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+
 2021-10-02  David Kilzer  <[email protected]>
 
         Replace WKProcessPoolWeakObserver (Direct) category with (direct) property attribute

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp (283469 => 283470)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2021-10-03 17:19:59 UTC (rev 283469)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2021-10-03 17:22:24 UTC (rev 283470)
@@ -842,12 +842,82 @@
 
 void ArgumentCoder<Length>::encode(Encoder& encoder, const Length& length)
 {
-    SimpleArgumentCoder<Length>::encode(encoder, length);
+    encoder << length.type() << length.hasQuirk();
+
+    switch (length.type()) {
+    case LengthType::Auto:
+    case LengthType::Undefined:
+        break;
+    case LengthType::Fixed:
+    case LengthType::Relative:
+    case LengthType::Intrinsic:
+    case LengthType::MinIntrinsic:
+    case LengthType::MinContent:
+    case LengthType::MaxContent:
+    case LengthType::FillAvailable:
+    case LengthType::FitContent:
+    case LengthType::Percent:
+        encoder << length.isFloat();
+        if (length.isFloat())
+            encoder << length.value();
+        else
+            encoder << length.intValue();
+        break;
+    case LengthType::Calculated:
+        ASSERT_NOT_REACHED();
+        break;
+    }
 }
 
 bool ArgumentCoder<Length>::decode(Decoder& decoder, Length& length)
 {
-    return SimpleArgumentCoder<Length>::decode(decoder, length);
+    LengthType type;
+    if (!decoder.decode(type))
+        return false;
+
+    bool hasQuirk;
+    if (!decoder.decode(hasQuirk))
+        return false;
+
+    switch (type) {
+    case LengthType::Auto:
+    case LengthType::Undefined:
+        length = Length(type);
+        return true;
+    case LengthType::Fixed:
+    case LengthType::Relative:
+    case LengthType::Intrinsic:
+    case LengthType::MinIntrinsic:
+    case LengthType::MinContent:
+    case LengthType::MaxContent:
+    case LengthType::FillAvailable:
+    case LengthType::FitContent:
+    case LengthType::Percent: {
+        bool isFloat;
+        if (!decoder.decode(isFloat))
+            return false;
+
+        if (isFloat) {
+            float value;
+            if (!decoder.decode(value))
+                return false;
+
+            length = Length(value, type, hasQuirk);
+        } else {
+            int value;
+            if (!decoder.decode(value))
+                return false;
+
+            length = Length(value, type, hasQuirk);
+        }
+        return true;
+    }
+    case LengthType::Calculated:
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    return false;
 }
 
 void ArgumentCoder<VelocityData>::encode(Encoder& encoder, const VelocityData& velocityData)

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h (283469 => 283470)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h	2021-10-03 17:19:59 UTC (rev 283469)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h	2021-10-03 17:22:24 UTC (rev 283470)
@@ -1060,4 +1060,22 @@
     >;
 };
 
+template<> struct EnumTraits<WebCore::LengthType> {
+    using values = EnumValues<
+        WebCore::LengthType,
+        WebCore::LengthType::Auto,
+        WebCore::LengthType::Relative,
+        WebCore::LengthType::Percent,
+        WebCore::LengthType::Fixed,
+        WebCore::LengthType::Intrinsic,
+        WebCore::LengthType::MinIntrinsic,
+        WebCore::LengthType::MinContent,
+        WebCore::LengthType::MaxContent,
+        WebCore::LengthType::FillAvailable,
+        WebCore::LengthType::FitContent,
+        WebCore::LengthType::Calculated,
+        WebCore::LengthType::Undefined
+    >;
+};
+
 } // namespace WTF
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to