Revision: 5508
Author:   [email protected]
Date:     Thu Jul 25 09:32:48 2013
Log:      Make startSES aware of accessor properties.
https://codereview.appspot.com/11778043/

* If a property is an accessor property, traverse the getter rather
  than invoking it and using its return value. This avoids possibly
  causing side-effects while traversing, and handles accessors on
  prototypes which throw if not called on an instance.
* Introduce a new whitelist value, 'accessor'; properties which
  are whitelisted as such but not actually accessors are rejected,
  as are properties which are accessors but whitelisted as data.
* Check syntax of whitelist as part of register().
* Shorten getThrowTypeError code by using 'gopd'.

[email protected]

http://code.google.com/p/google-caja/source/detail?r=5508

Modified:
 /trunk/src/com/google/caja/ses/startSES.js
 /trunk/src/com/google/caja/ses/whitelist.js

=======================================
--- /trunk/src/com/google/caja/ses/startSES.js  Sat Jul 13 09:31:10 2013
+++ /trunk/src/com/google/caja/ses/startSES.js  Thu Jul 25 09:32:48 2013
@@ -372,7 +372,7 @@
    * Obtain the ES5 singleton [[ThrowTypeError]].
    */
   function getThrowTypeError() {
- return Object.getOwnPropertyDescriptor(getThrowTypeError, "arguments").get;
+    return gopd(getThrowTypeError, "arguments").get;
   }


@@ -1384,10 +1384,14 @@
    * process "*" inheritance using the whitelist, by walking actual
    * superclass chains.
    */
+  var whitelistSymbols = [true, '*', 'accessor'];
   var whiteTable = WeakMap();
   function register(value, permit) {
     if (value !== Object(value)) { return; }
     if (typeof permit !== 'object') {
+      if (whitelistSymbols.indexOf(permit) < 0) {
+        fail('syntax error in whitelist; unexpected value: ' + permit);
+      }
       return;
     }
     var oldPermit = whiteTable.get(value);
@@ -1396,8 +1400,13 @@
     }
     whiteTable.set(value, permit);
     keys(permit).forEach(function(name) {
-      var sub = value[name];
-      register(sub, permit[name]);
+      // Use gopd to avoid invoking an accessor property.
+      // Mismatches between permit === 'accessor' and the property actually
+      // being an accessor property are caught later by clean().
+      var desc = gopd(value, name);
+      if (desc) {
+        register(desc.value, permit[name]);
+      }
     });
   }
   register(sharedImports, whitelist);
@@ -1407,7 +1416,7 @@
    * {@code base} object, and if so, with what Permit?
    *
    * <p>If it should be permitted, return the Permit (where Permit =
-   * true | "*" | Record(Permit)), all of which are
+   * true | "accessor" | "*" | Record(Permit)), all of which are
    * truthy. If it should not be permitted, return false.
    */
   function getPermit(base, name) {
@@ -1572,8 +1581,31 @@
       var path = prefix + (prefix ? '.' : '') + name;
       var p = getPermit(value, name);
       if (p) {
-        var sub = value[name];
-        clean(sub, path);
+        var desc = gopd(value, name);
+        if (hop.call(desc, 'value')) {
+          // Is a data property
+          var subValue = desc.value;
+          if (p === 'accessor') {
+            // We are not saying that it is safe for the prop to be
+            // unexpectedly not an accessor; rather, it will be deleted
+            // and thus made safe.
+            reportProperty(ses.severities.SAFE_SPEC_VIOLATION,
+                           'Not an accessor property', path);
+            cleanProperty(value, name, path);
+          } else {
+            clean(subValue, path);
+          }
+        } else {
+          // Is an accessor property (note symmetry with above case)
+          if (p !== 'accessor') {
+            reportProperty(ses.severities.SAFE_SPEC_VIOLATION,
+                           'Not a data property', path);
+            cleanProperty(value, name, path);
+          } else {
+            clean(desc.get, path + '<getter>');
+            clean(desc.set, path + '<setter>');
+          }
+        }
       } else {
         cleanProperty(value, name, path);
       }
=======================================
--- /trunk/src/com/google/caja/ses/whitelist.js Sat Jul 13 08:35:24 2013
+++ /trunk/src/com/google/caja/ses/whitelist.js Thu Jul 25 09:32:48 2013
@@ -48,6 +48,13 @@
  *     function) should be further tamed only according to the
  *     markings of the other objects it inherits from, like {@code
  *     "Function.prototype"} and {@code "Object.prototype").
+ *     If the property is an accessor property, it is not
+ *     whitelisted (as invoking an accessor might not be meaningful,
+ *     yet the accessor might return a value needing taming).
+ * <li>"accessor", in which case this accessor property is simply
+ *     whitelisted and its getter and/or setter are tamed according to
+ *     inheritance. If the property is not an accessor property, it is
+ *     not whitelisted.
  * <li>"*", in which case this property on this object is whitelisted,
  *     as is this property as inherited by all objects that inherit
  *     from this object. The values associated with all such properties

--

--- 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.


Reply via email to