Skip to content

Commit

Permalink
In ordinaryHasInstance, detect infinite prototype chains including Pr…
Browse files Browse the repository at this point in the history
…oxies

Summary:
With exotic objects, JS cannot prevent infinite prototype
chains from being constructed.

Reviewed By: tmikov

Differential Revision: D24006144

fbshipit-source-id: 80dee06efa5eef93556a0c3415de7db562e977e7
  • Loading branch information
mhorowitz authored and facebook-github-bot committed Sep 30, 2020
1 parent ea2b5aa commit 5d08b6e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
16 changes: 16 additions & 0 deletions lib/VM/Operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,15 @@ ordinaryHasInstance(Runtime *runtime, Handle<> constructor, Handle<> object) {
"function's '.prototype' is not an object in 'instanceof'");
}

// 6.1.7.3 Invariants of the Essential Internal Methods notes that
// detection of infinite prototype chains is not enforceable as an
// invariant if exotic objects exist in the chain. Most of the
// time, ScopedNativeDepthTracker will detect this. Here, we need to
// check that we're not repeating forever. Since ordinary object
// chains are verified at the time the parent is set, we count Proxy
// objects. Thus, any length chain of ordinary objects is ok.
constexpr unsigned int kMaxProxyCount = 1024;
unsigned int proxyCount = 0;
MutableHandle<JSObject> head{runtime, vmcast<JSObject>(object.get())};
GCScopeMarkerRAII gcScope{runtime};
// 6. Repeat
Expand All @@ -1454,6 +1463,13 @@ ordinaryHasInstance(Runtime *runtime, Handle<> constructor, Handle<> object) {
if (parentRes->get() == ctorPrototype.get()) {
return true;
}
if (head->isProxyObject()) {
++proxyCount;
if (proxyCount > kMaxProxyCount) {
return runtime->raiseRangeError(
"Maximum prototype chain length exceeded");
}
}
head = parentRes->get();
gcScope.flush();
}
Expand Down
12 changes: 12 additions & 0 deletions test/hermes/instanceof.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,15 @@ print( (new ChildObj()) instanceof BoundBase);
//CHECK-NEXT: true
print( (new ChildObj()) instanceof BoundChild);
//CHECK-NEXT: true

var a = new Proxy({}, {});
var b = Object.create(a);
var c = Object.create(b);
a.__proto__ = c;
try {
b instanceof Date;
} catch (e) {
print("caught", e.name, e.message);
}
//CHECK-NEXT: caught RangeError Maximum prototype chain length exceeded

0 comments on commit 5d08b6e

Please sign in to comment.