浏览代码

LibJS: Don't change offset when reconfiguring property in unique shape

When changing the attributes of an existing property of an object with
unique shape we must not change the PropertyMetadata offset.
Doing so without resizing the underlying storage vector caused an OOB
write crash.

Fixes #3735.
Linus Groh 4 年之前
父节点
当前提交
a5bf6cfff9
共有 2 个文件被更改,包括 14 次插入2 次删除
  1. 4 2
      Libraries/LibJS/Runtime/Shape.cpp
  2. 10 0
      Libraries/LibJS/Tests/builtins/Object/Object.defineProperty.js

+ 4 - 2
Libraries/LibJS/Runtime/Shape.cpp

@@ -195,8 +195,10 @@ void Shape::reconfigure_property_in_unique_shape(const StringOrSymbol& property_
 {
 {
     ASSERT(is_unique());
     ASSERT(is_unique());
     ASSERT(m_property_table);
     ASSERT(m_property_table);
-    ASSERT(m_property_table->contains(property_name));
-    m_property_table->set(property_name, { m_property_table->size(), attributes });
+    auto it = m_property_table->find(property_name);
+    ASSERT(it != m_property_table->end());
+    it->value.attributes = attributes;
+    m_property_table->set(property_name, it->value);
 }
 }
 
 
 void Shape::remove_property_from_unique_shape(const StringOrSymbol& property_name, size_t offset)
 void Shape::remove_property_from_unique_shape(const StringOrSymbol& property_name, size_t offset)

+ 10 - 0
Libraries/LibJS/Tests/builtins/Object/Object.defineProperty.js

@@ -148,6 +148,16 @@ describe("normal functionality", () => {
         expect((o[s] = 5)).toBe(5);
         expect((o[s] = 5)).toBe(5);
         expect((o[s] = 4)).toBe(4);
         expect((o[s] = 4)).toBe(4);
     });
     });
+
+    test("issue #3735, reconfiguring property in unique shape", () => {
+        const o = {};
+        // In LibJS an object with more than 100 properties gets a unique shape
+        for (let i = 0; i < 101; ++i) {
+            o[`property${i}`] = i;
+        }
+        Object.defineProperty(o, "x", { configurable: true });
+        Object.defineProperty(o, "x", { configurable: false });
+    });
 });
 });
 
 
 describe("errors", () => {
 describe("errors", () => {