diff options
Diffstat (limited to 'js/src/vm/UbiNodeCensus.cpp')
-rw-r--r-- | js/src/vm/UbiNodeCensus.cpp | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/js/src/vm/UbiNodeCensus.cpp b/js/src/vm/UbiNodeCensus.cpp index ba3ccd0898..7e33341d30 100644 --- a/js/src/vm/UbiNodeCensus.cpp +++ b/js/src/vm/UbiNodeCensus.cpp @@ -6,6 +6,8 @@ #include "js/UbiNodeCensus.h" +#include "mozilla/ScopeExit.h" + #include "builtin/MapObject.h" #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/Printer.h" @@ -1062,17 +1064,19 @@ JS_PUBLIC_API bool CensusHandler::operator()( /*** Parsing Breakdowns *****************************************************/ -static CountTypePtr ParseChildBreakdown(JSContext* cx, HandleObject breakdown, - PropertyName* prop) { +static CountTypePtr ParseChildBreakdown( + JSContext* cx, HandleObject breakdown, PropertyName* prop, + MutableHandle<GCVector<JSLinearString*>> seen) { RootedValue v(cx); if (!GetProperty(cx, breakdown, breakdown, prop, &v)) { return nullptr; } - return ParseBreakdown(cx, v); + return ParseBreakdown(cx, v, seen); } -JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, - HandleValue breakdownValue) { +JS_PUBLIC_API CountTypePtr +ParseBreakdown(JSContext* cx, HandleValue breakdownValue, + MutableHandle<GCVector<JSLinearString*>> seen) { if (breakdownValue.isUndefined()) { // Construct the default type, { by: 'count' } CountTypePtr simple(cx->new_<SimpleCount>()); @@ -1097,6 +1101,24 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, return nullptr; } + for (auto candidate : seen.get()) { + if (EqualStrings(by, candidate)) { + UniqueChars byBytes = QuoteString(cx, by, '"'); + if (!byBytes) { + return nullptr; + } + + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DEBUG_CENSUS_BREAKDOWN_NESTED, + byBytes.get()); + return nullptr; + } + } + if (!seen.append(by)) { + return nullptr; + } + auto popper = mozilla::MakeScopeExit([&]() { seen.popBack(); }); + if (StringEqualsLiteral(by, "count")) { RootedValue countValue(cx), bytesValue(cx); if (!GetProperty(cx, breakdown, breakdown, cx->names().count, @@ -1140,13 +1162,14 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, } if (StringEqualsLiteral(by, "objectClass")) { - CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then)); + CountTypePtr thenType( + ParseChildBreakdown(cx, breakdown, cx->names().then, seen)); if (!thenType) { return nullptr; } CountTypePtr otherType( - ParseChildBreakdown(cx, breakdown, cx->names().other)); + ParseChildBreakdown(cx, breakdown, cx->names().other, seen)); if (!otherType) { return nullptr; } @@ -1156,27 +1179,27 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, if (StringEqualsLiteral(by, "coarseType")) { CountTypePtr objectsType( - ParseChildBreakdown(cx, breakdown, cx->names().objects)); + ParseChildBreakdown(cx, breakdown, cx->names().objects, seen)); if (!objectsType) { return nullptr; } CountTypePtr scriptsType( - ParseChildBreakdown(cx, breakdown, cx->names().scripts)); + ParseChildBreakdown(cx, breakdown, cx->names().scripts, seen)); if (!scriptsType) { return nullptr; } CountTypePtr stringsType( - ParseChildBreakdown(cx, breakdown, cx->names().strings)); + ParseChildBreakdown(cx, breakdown, cx->names().strings, seen)); if (!stringsType) { return nullptr; } CountTypePtr otherType( - ParseChildBreakdown(cx, breakdown, cx->names().other)); + ParseChildBreakdown(cx, breakdown, cx->names().other, seen)); if (!otherType) { return nullptr; } CountTypePtr domNodeType( - ParseChildBreakdown(cx, breakdown, cx->names().domNode)); + ParseChildBreakdown(cx, breakdown, cx->names().domNode, seen)); if (!domNodeType) { return nullptr; } @@ -1186,7 +1209,8 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, } if (StringEqualsLiteral(by, "internalType")) { - CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then)); + CountTypePtr thenType( + ParseChildBreakdown(cx, breakdown, cx->names().then, seen)); if (!thenType) { return nullptr; } @@ -1195,7 +1219,8 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, } if (StringEqualsLiteral(by, "descriptiveType")) { - CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then)); + CountTypePtr thenType( + ParseChildBreakdown(cx, breakdown, cx->names().then, seen)); if (!thenType) { return nullptr; } @@ -1203,12 +1228,13 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, } if (StringEqualsLiteral(by, "allocationStack")) { - CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then)); + CountTypePtr thenType( + ParseChildBreakdown(cx, breakdown, cx->names().then, seen)); if (!thenType) { return nullptr; } CountTypePtr noStackType( - ParseChildBreakdown(cx, breakdown, cx->names().noStack)); + ParseChildBreakdown(cx, breakdown, cx->names().noStack, seen)); if (!noStackType) { return nullptr; } @@ -1217,13 +1243,14 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx, } if (StringEqualsLiteral(by, "filename")) { - CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then)); + CountTypePtr thenType( + ParseChildBreakdown(cx, breakdown, cx->names().then, seen)); if (!thenType) { return nullptr; } CountTypePtr noFilenameType( - ParseChildBreakdown(cx, breakdown, cx->names().noFilename)); + ParseChildBreakdown(cx, breakdown, cx->names().noFilename, seen)); if (!noFilenameType) { return nullptr; } @@ -1307,8 +1334,9 @@ JS_PUBLIC_API bool ParseCensusOptions(JSContext* cx, Census& census, return false; } + Rooted<GCVector<JSLinearString*>> seen(cx, cx); outResult = breakdown.isUndefined() ? GetDefaultBreakdown(cx) - : ParseBreakdown(cx, breakdown); + : ParseBreakdown(cx, breakdown, &seen); return !!outResult; } |