From fdd974b7ef4fb3f38c266f0f16d9b68f84f40bca Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 5 Jan 2021 12:02:59 +0100 Subject: [PATCH] LibJS: Fix UB downcast during GlobalObject construction When constructing a GlobalObject, it has to pass itself as the global object to its own Shape. Since this is done in the Object constructor, and Object is a base class of GlobalObject, it's not yet valid to cast "this" to a GlobalObject*. Fix this by having Shape store the global object as an Object& and move Shape::global_object() to GlobalObject.h where we can at least perform a valid static_cast in the getter. Found by oss-fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29267 --- Libraries/LibJS/Runtime/GlobalObject.h | 5 +++++ Libraries/LibJS/Runtime/Object.cpp | 2 +- Libraries/LibJS/Runtime/Shape.cpp | 2 +- Libraries/LibJS/Runtime/Shape.h | 6 +++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Libraries/LibJS/Runtime/GlobalObject.h b/Libraries/LibJS/Runtime/GlobalObject.h index 0b2163e3f4..d3b7041e43 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.h +++ b/Libraries/LibJS/Runtime/GlobalObject.h @@ -125,4 +125,9 @@ inline void GlobalObject::add_constructor(const FlyString& property_name, Constr define_property(property_name, constructor, Attribute::Writable | Attribute::Configurable); } +inline GlobalObject* Shape::global_object() const +{ + return static_cast(m_global_object); +} + } diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index bb03709e5d..87a9d75dd5 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -90,7 +90,7 @@ Object* Object::create_empty(GlobalObject& global_object) Object::Object(GlobalObjectTag) { // This is the global object - m_shape = heap().allocate_without_global_object(static_cast(*this)); + m_shape = heap().allocate_without_global_object(*this); } Object::Object(ConstructWithoutPrototypeTag, GlobalObject& global_object) diff --git a/Libraries/LibJS/Runtime/Shape.cpp b/Libraries/LibJS/Runtime/Shape.cpp index 42cfcaa73e..1f74b14471 100644 --- a/Libraries/LibJS/Runtime/Shape.cpp +++ b/Libraries/LibJS/Runtime/Shape.cpp @@ -72,7 +72,7 @@ Shape::Shape(ShapeWithoutGlobalObjectTag) { } -Shape::Shape(GlobalObject& global_object) +Shape::Shape(Object& global_object) : m_global_object(&global_object) { } diff --git a/Libraries/LibJS/Runtime/Shape.h b/Libraries/LibJS/Runtime/Shape.h index aef09cd375..1d2bd51037 100644 --- a/Libraries/LibJS/Runtime/Shape.h +++ b/Libraries/LibJS/Runtime/Shape.h @@ -65,7 +65,7 @@ public: enum class ShapeWithoutGlobalObjectTag { Tag }; explicit Shape(ShapeWithoutGlobalObjectTag); - explicit Shape(GlobalObject&); + explicit Shape(Object& global_object); Shape(Shape& previous_shape, const StringOrSymbol& property_name, PropertyAttributes attributes, TransitionType); Shape(Shape& previous_shape, Object* new_prototype); @@ -78,7 +78,7 @@ public: bool is_unique() const { return m_unique; } Shape* create_unique_clone() const; - GlobalObject* global_object() const { return m_global_object; } + GlobalObject* global_object() const; Object* prototype() { return m_prototype; } const Object* prototype() const { return m_prototype; } @@ -110,7 +110,7 @@ private: TransitionType m_transition_type : 6 { TransitionType::Invalid }; bool m_unique : 1 { false }; - GlobalObject* m_global_object { nullptr }; + Object* m_global_object { nullptr }; mutable OwnPtr> m_property_table;