Reviewers: felix8a,
Description:
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.
Please review this at https://codereview.appspot.com/13202043/
Affected files:
M tests/com/google/caja/plugin/test-scan-core.js
M tests/com/google/caja/plugin/test-scan-guest.js
Index: tests/com/google/caja/plugin/test-scan-guest.js
===================================================================
--- tests/com/google/caja/plugin/test-scan-guest.js (revision 5577)
+++ tests/com/google/caja/plugin/test-scan-guest.js (working copy)
@@ -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);
Index: tests/com/google/caja/plugin/test-scan-core.js
===================================================================
--- tests/com/google/caja/plugin/test-scan-core.js (revision 5577)
+++ tests/com/google/caja/plugin/test-scan-core.js (working copy)
@@ -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; });
@@ -664,6 +675,11 @@
return;
}
+ if (context.getDepth() > 16) {
+ noteGap('Depth limit reached', context);
+ return;
+ }
+
// deduplication and logging
var seenName = seenTable.get(object);
if (seenName) {
@@ -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) {
--
---
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.