зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
eb4a9c2169
Коммит
b48a9ddb65
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче