Skip to content

Commit 77397c5

Browse files
aduh95targos
authored andcommitted
util: do not rely on mutable Object and Function' constructor prop
PR-URL: #56188Fixes: #55924 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Jordan Harband <[email protected]>
1 parent f3b3ff8 commit 77397c5

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

‎lib/internal/util/inspect.js‎

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ const{
2222
DatePrototypeToISOString,
2323
DatePrototypeToString,
2424
ErrorPrototypeToString,
25+
Function,
26+
FunctionPrototype,
2527
FunctionPrototypeBind,
2628
FunctionPrototypeCall,
29+
FunctionPrototypeSymbolHasInstance,
2730
FunctionPrototypeToString,
2831
JSONStringify,
2932
MapPrototypeEntries,
@@ -50,6 +53,7 @@ const{
5053
ObjectGetPrototypeOf,
5154
ObjectIs,
5255
ObjectKeys,
56+
ObjectPrototype,
5357
ObjectPrototypeHasOwnProperty,
5458
ObjectPrototypePropertyIsEnumerable,
5559
ObjectSeal,
@@ -593,10 +597,26 @@ function isInstanceof(object, proto){
593597
}
594598
}
595599

600+
// Special-case for some builtin prototypes in case their `constructor` property has been tampered.
601+
constwellKnownPrototypes=newSafeMap();
602+
wellKnownPrototypes.set(ObjectPrototype,{name: 'Object',constructor: Object});
603+
wellKnownPrototypes.set(FunctionPrototype,{name: 'Function',constructor: Function});
604+
596605
functiongetConstructorName(obj,ctx,recurseTimes,protoProps){
597606
letfirstProto;
598607
consttmp=obj;
599608
while(obj||isUndetectableObject(obj)){
609+
constwellKnownPrototypeNameAndConstructor=wellKnownPrototypes.get(obj);
610+
if(wellKnownPrototypeNameAndConstructor!=null){
611+
const{ name, constructor }=wellKnownPrototypeNameAndConstructor;
612+
if(FunctionPrototypeSymbolHasInstance(constructor,tmp)){
613+
if(protoProps!==undefined&&firstProto!==obj){
614+
addPrototypeProperties(
615+
ctx,tmp,firstProto||tmp,recurseTimes,protoProps);
616+
}
617+
returnname;
618+
}
619+
}
600620
constdescriptor=ObjectGetOwnPropertyDescriptor(obj,'constructor');
601621
if(descriptor!==undefined&&
602622
typeofdescriptor.value==='function'&&
@@ -954,7 +974,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray){
954974
if(noIterator){
955975
keys=getKeys(value,ctx.showHidden);
956976
braces=['{','}'];
957-
if(constructor==='Object'){
977+
if(typeofvalue==='function'){
978+
base=getFunctionBase(value,constructor,tag);
979+
if(keys.length===0&&protoProps===undefined)
980+
returnctx.stylize(base,'special');
981+
}elseif(constructor==='Object'){
958982
if(isArgumentsObject(value)){
959983
braces[0]='[Arguments]{';
960984
}elseif(tag!==''){
@@ -963,10 +987,6 @@ function formatRaw(ctx, value, recurseTimes, typedArray){
963987
if(keys.length===0&&protoProps===undefined){
964988
return`${braces[0]}}`;
965989
}
966-
}elseif(typeofvalue==='function'){
967-
base=getFunctionBase(value,constructor,tag);
968-
if(keys.length===0&&protoProps===undefined)
969-
returnctx.stylize(base,'special');
970990
}elseif(isRegExp(value)){
971991
// Make RegExps say that they are RegExps
972992
base=RegExpPrototypeToString(

‎test/parallel/test-util-inspect.js‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3323,3 +3323,33 @@ assert.strictEqual(
33233323
}
33243324
}),'{[Symbol(Symbol.iterator)]: [Getter] }');
33253325
}
3326+
3327+
{
3328+
consto={};
3329+
const{prototype: BuiltinPrototype}=Object;
3330+
constdesc=Reflect.getOwnPropertyDescriptor(BuiltinPrototype,'constructor');
3331+
Object.defineProperty(BuiltinPrototype,'constructor',{
3332+
get: ()=>BuiltinPrototype,
3333+
configurable: true,
3334+
});
3335+
assert.strictEqual(
3336+
util.inspect(o),
3337+
'{}',
3338+
);
3339+
Object.defineProperty(BuiltinPrototype,'constructor',desc);
3340+
}
3341+
3342+
{
3343+
consto={f(){}};
3344+
const{prototype: BuiltinPrototype}=Function;
3345+
constdesc=Reflect.getOwnPropertyDescriptor(BuiltinPrototype,'constructor');
3346+
Object.defineProperty(BuiltinPrototype,'constructor',{
3347+
get: ()=>BuiltinPrototype,
3348+
configurable: true,
3349+
});
3350+
assert.strictEqual(
3351+
util.inspect(o),
3352+
'{f: [Function: f] }',
3353+
);
3354+
Object.defineProperty(BuiltinPrototype,'constructor',desc);
3355+
}

0 commit comments

Comments
(0)