From 7858f87ae5b7b5a136df6c64ac68373f8c669610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= Date: Mon, 21 Mar 2022 17:58:31 +0200 Subject: [PATCH] jscript: Throw error when attempting to set circular __proto__ chains. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gabriel Ivăncescu Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/jscript/dispex.c | 5 +++++ dlls/jscript/error.c | 1 + dlls/jscript/jscript.h | 1 + dlls/jscript/jscript.rc | 1 + dlls/jscript/resource.h | 1 + dlls/mshtml/tests/documentmode.js | 13 +++++++++++++ 6 files changed, 22 insertions(+) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index a74840ef701..eff91e93bbf 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2708,11 +2708,16 @@ HRESULT jsdisp_define_data_property(jsdisp_t *obj, const WCHAR *name, unsigned f HRESULT jsdisp_change_prototype(jsdisp_t *obj, jsdisp_t *proto) { + jsdisp_t *iter; DWORD i; if(obj->prototype == proto) return S_OK; + for(iter = proto; iter; iter = iter->prototype) + if(iter == obj) + return JS_E_CYCLIC_PROTO_VALUE; + if(obj->prototype) { for(i = 0; i < obj->prop_cnt; i++) if(obj->props[i].type == PROP_PROTREF) diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 6f17699a210..4db95e5f9fe 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -477,6 +477,7 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_ENUMERATOR_EXPECTED: case JS_E_REGEXP_EXPECTED: case JS_E_ARRAY_EXPECTED: + case JS_E_CYCLIC_PROTO_VALUE: case JS_E_OBJECT_NONEXTENSIBLE: case JS_E_NONCONFIGURABLE_REDEFINED: case JS_E_NONWRITABLE_MODIFIED: diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 4a4d303f563..96f2270ad98 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -518,6 +518,7 @@ static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags) #define JS_E_PRECISION_OUT_OF_RANGE MAKE_JSERROR(IDS_PRECISION_OUT_OF_RANGE) #define JS_E_INVALID_LENGTH MAKE_JSERROR(IDS_INVALID_LENGTH) #define JS_E_ARRAY_EXPECTED MAKE_JSERROR(IDS_ARRAY_EXPECTED) +#define JS_E_CYCLIC_PROTO_VALUE MAKE_JSERROR(IDS_CYCLIC_PROTO_VALUE) #define JS_E_OBJECT_NONEXTENSIBLE MAKE_JSERROR(IDS_OBJECT_NONEXTENSIBLE) #define JS_E_NONCONFIGURABLE_REDEFINED MAKE_JSERROR(IDS_NONCONFIGURABLE_REDEFINED) #define JS_E_NONWRITABLE_MODIFIED MAKE_JSERROR(IDS_NONWRITABLE_MODIFIED) diff --git a/dlls/jscript/jscript.rc b/dlls/jscript/jscript.rc index 50e2c30700e..38a49d9b850 100644 --- a/dlls/jscript/jscript.rc +++ b/dlls/jscript/jscript.rc @@ -70,6 +70,7 @@ STRINGTABLE IDS_INVALID_LENGTH "Array length must be a finite positive integer" IDS_ARRAY_EXPECTED "Array object expected" IDS_INVALID_WRITABLE_PROP_DESC "'writable' attribute on the property descriptor cannot be set to 'true' on this object" + IDS_CYCLIC_PROTO_VALUE "Cyclic __proto__ value" IDS_OBJECT_NONEXTENSIBLE "Cannot define property '|': object is not extensible" IDS_NONCONFIGURABLE_REDEFINED "Cannot redefine non-configurable property '|'" IDS_NONWRITABLE_MODIFIED "Cannot modify non-writable property '|'" diff --git a/dlls/jscript/resource.h b/dlls/jscript/resource.h index b17f9fbd561..07934311a1b 100644 --- a/dlls/jscript/resource.h +++ b/dlls/jscript/resource.h @@ -68,6 +68,7 @@ #define IDS_INVALID_LENGTH 0x13A5 #define IDS_ARRAY_EXPECTED 0x13A7 #define IDS_INVALID_WRITABLE_PROP_DESC 0x13AC +#define IDS_CYCLIC_PROTO_VALUE 0x13B0 #define IDS_OBJECT_NONEXTENSIBLE 0x13D5 #define IDS_NONCONFIGURABLE_REDEFINED 0x13D6 #define IDS_NONWRITABLE_MODIFIED 0x13D7 diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 43ebd56eb7e..51a8fe0f877 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1390,6 +1390,19 @@ sync_test("__proto__", function() { }catch(e) { ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on null threw exception " + e.number); } + + x = {}; + r = Object.create(x); + ok(r.__proto__ === x, "r.__proto__ = " + r.__proto__); + r = Object.create(r); + ok(r.__proto__.__proto__ === x, "r.__proto__.__proto__ = " + r.__proto__.__proto__); + try { + x.__proto__ = r; + ok(false, "expected exception setting circular proto chain"); + }catch(e) { + ok(e.number === 0xa13b0 - 0x80000000 && e.name === "TypeError", + "setting circular proto chain threw exception " + e.number + " (" + e.name + ")"); + } }); async_test("postMessage", function() {