Bug 998344 - Prevent console autocompletion on objects with a large number of properties. r=msucan

--HG--
extra : rebase_source : 6ea291d29775b4894f084e93f533a3ca5ddfb33e
This commit is contained in:
Brian Grinstead 2014-08-06 07:56:00 -04:00
Родитель eb4a9c2169
Коммит b48a9ddb65
2 изменённых файлов: 69 добавлений и 8 удалений

Просмотреть файл

@ -16,6 +16,9 @@ SimpleTest.waitForExplicitFinish();
let gState;
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let {MAX_AUTOCOMPLETE_ATTEMPTS,MAX_AUTOCOMPLETIONS} = devtools.require("devtools/toolkit/webconsole/utils");
function startTest()
{
removeEventListener("load", startTest);
@ -35,10 +38,21 @@ function onAttach(aState, aResponse)
top.foobarObject.omgstr = "foobarz" +
(new Array(DebuggerServer.LONG_STRING_LENGTH * 2)).join("abb");
top.largeObject1 = Object.create(null);
for (let i = 0; i < MAX_AUTOCOMPLETE_ATTEMPTS + 1; i++) {
top.largeObject1['a' + i] = i;
}
top.largeObject2 = Object.create(null);
for (let i = 0; i < MAX_AUTOCOMPLETIONS * 2; i++) {
top.largeObject2['a' + i] = i;
}
gState = aState;
let tests = [doAutocomplete1, doAutocomplete2, doAutocomplete3,
doAutocomplete4, doSimpleEval, doWindowEval, doEvalWithException,
doAutocomplete4, doAutocompleteLarge1, doAutocompleteLarge2,
doSimpleEval, doWindowEval, doEvalWithException,
doEvalWithHelper, doEvalString, doEvalLongString];
runTests(tests, testEnd);
}
@ -112,6 +126,39 @@ function onAutocomplete4(aResponse)
nextTest();
}
function doAutocompleteLarge1()
{
// Check that completion requests with too large objects will
// have no suggestions.
info("test autocomplete for 'window.largeObject1.'");
gState.client.autocomplete("window.largeObject1.", 20, onAutocompleteLarge1);
}
function onAutocompleteLarge1(aResponse)
{
ok(!aResponse.matchProp, "matchProp");
info (aResponse.matches.join("|"));
is(aResponse.matches.length, 0, "Bailed out with too many properties");
nextTest();
}
function doAutocompleteLarge2()
{
// Check that completion requests with pretty large objects will
// have MAX_AUTOCOMPLETIONS suggestions
info("test autocomplete for 'window.largeObject2.'");
gState.client.autocomplete("window.largeObject2.", 20, onAutocompleteLarge2);
}
function onAutocompleteLarge2(aResponse)
{
ok(!aResponse.matchProp, "matchProp");
is(aResponse.matches.length, MAX_AUTOCOMPLETIONS, "matches.length is MAX_AUTOCOMPLETIONS");
nextTest();
}
function doSimpleEval()
{
info("test eval '2+2'");

Просмотреть файл

@ -33,6 +33,15 @@ const REGEX_MATCH_FUNCTION_ARGS = /^\(?function\s*[^\s(]*\s*\((.+?)\)/;
// Number of terminal entries for the self-xss prevention to go away
const CONSOLE_ENTRY_THRESHOLD = 5
// Provide an easy way to bail out of even attempting an autocompletion
// if an object has way too many properties. Protects against large objects
// with numeric values that wouldn't be tallied towards MAX_AUTOCOMPLETIONS.
const MAX_AUTOCOMPLETE_ATTEMPTS = exports.MAX_AUTOCOMPLETE_ATTEMPTS = 100000;
// Prevent iterating over too many properties during autocomplete suggestions.
const MAX_AUTOCOMPLETIONS = exports.MAX_AUTOCOMPLETIONS = 1500;
let WebConsoleUtils = {
/**
* Convenience function to unwrap a wrapped object.
@ -710,8 +719,6 @@ const OPEN_CLOSE_BODY = {
"(": ")",
};
const MAX_COMPLETIONS = 1500;
/**
* Analyses a given string to find the last statement that is interesting for
* later completion.
@ -1044,11 +1051,22 @@ function getMatchedProps(aObj, aMatch)
function getMatchedProps_impl(aObj, aMatch, {chainIterator, getProperties})
{
let matches = new Set();
let numProps = 0;
// We need to go up the prototype chain.
let iter = chainIterator(aObj);
for (let obj of iter) {
let props = getProperties(obj);
numProps += props.length;
// If there are too many properties to event attempt autocompletion,
// or if we have already added the max number, then stop looping
// and return the partial set that has already been discovered.
if (numProps >= MAX_AUTOCOMPLETE_ATTEMPTS ||
matches.size >= MAX_AUTOCOMPLETIONS) {
break;
}
for (let i = 0; i < props.length; i++) {
let prop = props[i];
if (prop.indexOf(aMatch) != 0) {
@ -1062,14 +1080,10 @@ function getMatchedProps_impl(aObj, aMatch, {chainIterator, getProperties})
matches.add(prop);
}
if (matches.size > MAX_COMPLETIONS) {
if (matches.size >= MAX_AUTOCOMPLETIONS) {
break;
}
}
if (matches.size > MAX_COMPLETIONS) {
break;
}
}
return {