Revision: 5578
Author: [email protected]
Date: Mon Aug 26 17:08:41 2013 UTC
Log: Work around infinite recursion in scanner on Chrome.
https://codereview.appspot.com/13202043
This is a quick fix for
<https://code.google.com/p/google-caja/issues/detail?id=1848>
which should be replaced with something more principled once we figure
out what that is.
* Do not PLAIN_CALL any getter with a property named "stack".
* Add a limit for depth of traversal. (This will cause the test to fail
rather than run out of time/memory, in the event of any future similar
problems.)
Supporting changes:
* Move all definitions in test-scan-guest relating to Error to one place
and use new Ref definition style.
[email protected]
http://code.google.com/p/google-caja/source/detail?r=5578
Modified:
/trunk/tests/com/google/caja/plugin/test-scan-core.js
/trunk/tests/com/google/caja/plugin/test-scan-guest.js
=======================================
--- /trunk/tests/com/google/caja/plugin/test-scan-core.js Fri Aug 23
17:58:39 2013 UTC
+++ /trunk/tests/com/google/caja/plugin/test-scan-core.js Mon Aug 26
17:08:41 2013 UTC
@@ -421,6 +421,7 @@
*
* @param object The object of interest.
* @param path A textual short description of how we got the object.
+ * @param depth Count of sequential operations performed to get the
object.
* @param getSelfC Returns the context of something to use instead of
the
* object on methods (i.e. an instance if the object is a
prototype).
* @param getThisArgC Ditto but for the thisArg for invoking the object
@@ -430,7 +431,8 @@
* attempting to obtain an instance of a
not-actually-a-constructor.
* @param getProgram A thunk for program source which returns the
object.
*/
- function makeContext(object, path, getSelfC, getThisArgC, getProgram) {
+ function makeContext(object, path, depth, getSelfC, getThisArgC,
+ getProgram) {
var context;
var prefix = path === '' ? '' : path + '.';
if (getSelfC === 'self') {
@@ -449,6 +451,7 @@
},
get: function() { return object; },
getPath: function() { return path; },
+ getDepth: function() { return depth; },
getter: function(name, getter) {
function getterProgram() {
return 'Object.getOwnPropertyDescriptor(' +
@@ -460,6 +463,7 @@
return makeContext(
getter,
prefix + 'get ' + name,
+ depth + 1,
'self',
getSelfC,
getterProgram);
@@ -468,6 +472,7 @@
return makeContext(
setter,
prefix + 'set ' + name,
+ depth + 1,
'self',
getSelfC,
function() {
@@ -481,12 +486,13 @@
if (p === 'prototype') {
// When invoking methods on a prototype, use an instance of
this
// ctor instead as 'this'.
- var protoctx = makeContext(pval, subpath,
+ var protoctx = makeContext(pval, subpath, depth + 1,
function() {
var selfC = getSelfC();
return makeContext(
obtainInstance(selfC.get(), selfC),
path + '<instance>',
+ depth + 1,
'self',
function() { return noThisContext; },
protoctx,
@@ -503,6 +509,7 @@
return makeContext(
pval,
subpath,
+ depth + 1,
getSelfC,
function() { return noThisContext; },
function() {
@@ -512,6 +519,7 @@
return makeContext(
pval,
subpath,
+ depth + 1,
'self',
getSelfC,
function() {
@@ -528,6 +536,7 @@
return makeContext(
ival,
path + argstr + (thrown ? ' thrown ' : ''),
+ depth + 1,
'self',
getSelfC,
function() {
@@ -552,6 +561,7 @@
undefined,
'<noThis>',
'self',
+ 0,
function() { return noThisContext; },
function() { return 'undefined'; });
@@ -560,6 +570,7 @@
return makeContext(
o,
path,
+ 0,
'self',
function() { return noThisContext; },
function() { return code; });
@@ -663,6 +674,11 @@
log(path, ' FILTERED\n');
return;
}
+
+ if (context.getDepth() > 16) {
+ noteGap('Depth limit reached', context);
+ return;
+ }
// deduplication and logging
var seenName = seenTable.get(object);
@@ -706,7 +722,12 @@
var didSomeCall = false;
var didNonThrowingCall = false;
- var shouldPlainCall = isNativeFunction(object);
+ // TODO(kpreid): the '.get stack' rule is a misplaced kludge
which
+ // should at least live in the caller. It is needed to avoid
infinite
+ // descent. See
+ // <https://code.google.com/p/google-caja/issues/detail?id=1848>.
+ var shouldPlainCall = isNativeFunction(object) &&
+ !(/\.get stack/.test(path));
var didPlainCall = false;
var doInvocation = function(tuple) {
=======================================
--- /trunk/tests/com/google/caja/plugin/test-scan-guest.js Fri Aug 23
17:58:39 2013 UTC
+++ /trunk/tests/com/google/caja/plugin/test-scan-guest.js Mon Aug 26
17:08:41 2013 UTC
@@ -705,14 +705,25 @@
argsByAnyFrame('String.prototype.trimLeft', genNoArgMethod);
argsByAnyFrame('String.prototype.trimRight', genNoArgMethod);
- var genErrorConstruct = genAllCall(genString);
- argsByAnyFrame('Error', genErrorConstruct);
- argsByAnyFrame('EvalError', genErrorConstruct);
- argsByAnyFrame('RangeError', genErrorConstruct);
- argsByAnyFrame('ReferenceError', genErrorConstruct);
- argsByAnyFrame('SyntaxError', genErrorConstruct);
- argsByAnyFrame('TypeError', genErrorConstruct);
- argsByAnyFrame('URIError', genErrorConstruct);
+ // Error objects
+ functionArgs.set(Ref.all(
+ RefAnyFrame('Error'),
+ RefAnyFrame('EvalError'),
+ RefAnyFrame('RangeError'),
+ RefAnyFrame('ReferenceError'),
+ RefAnyFrame('SyntaxError'),
+ RefAnyFrame('TypeError'),
+ RefAnyFrame('URIError')),
+ genAllCall(genString));
+ expectedUnfrozen.mark(Ref.all(
+ Ref.ctor(Error),
+ Ref.ctor(tamingEnv.Error)));
+ // fresh-on-every-instance getter, on at least Chrome 31.0.1609.0
+ expectedUnfrozen.mark(Ref.all(
+ Ref.path('.get stack'),
+ Ref.path('.set stack'),
+ Ref.path('.get stack.prototype'),
+ Ref.path('.set stack.prototype')));
argsByIdentity(cajaVM.allKeys, genMethod(genJSONValue));
function cweF1(ejector) {
@@ -1043,7 +1054,6 @@
argsByProp('getBoundingClientRect', freshResult(genNoArgMethod));
argsByProp('updateStyle', genNoArgMethod);
argsByProp('getPropertyValue', genMethod(genCSSPropertyName));
- argsByProp('set stack', G.none);
argsByProp('getContext', genMethod(G.value(undefined,
null, 'bogus', '2d',
'webgl', 'experimental-webgl')));
argsByProp('querySelector', genMethod(genCSSSelector));
@@ -1202,7 +1212,6 @@
argsByProp('stopPropagation', G.none);
argsByProp('preventDefault', G.none);
- var tamingFrameError = tamingEnv.Error;
expectedUnfrozen.addSpecialCase(function(context) {
var object = context.get();
var path = context.getPath();
@@ -1243,8 +1252,6 @@
expectedUnfrozen.setByConstructor(Node, true);
assertTrue(location.constructor !== Object);
expectedUnfrozen.setByConstructor(location.constructor, true);
- expectedUnfrozen.setByConstructor(Error, true);
- expectedUnfrozen.setByConstructor(tamingEnv.Error, true);
// these types can't be coherently exported due to ArrayLike gimmick
//expectedUnfrozen.setByConstructor(NodeList, true);
//expectedUnfrozen.setByConstructor(NamedNodeMap, true);
--
---
You received this message because you are subscribed to the Google Groups "Google Caja Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.