You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2016/09/09 13:28:34 UTC

[1/4] couchdb commit: updated refs/heads/master to d6abc18

Repository: couchdb
Updated Branches:
  refs/heads/master aae4ff745 -> d6abc18f2


do not pollute the global scope


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/4dbd858e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/4dbd858e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/4dbd858e

Branch: refs/heads/master
Commit: 4dbd858e4b3babb454a605f5d429e118f02c05b2
Parents: aae4ff7
Author: Randall Leeds <ra...@apache.org>
Authored: Sat Feb 20 18:28:24 2016 -0800
Committer: Robert Newson <rn...@apache.org>
Committed: Fri Sep 9 14:09:35 2016 +0100

----------------------------------------------------------------------
 support/build_js.escript | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/4dbd858e/support/build_js.escript
----------------------------------------------------------------------
diff --git a/support/build_js.escript b/support/build_js.escript
index 5050fd6..0b3a859 100644
--- a/support/build_js.escript
+++ b/support/build_js.escript
@@ -40,13 +40,15 @@ main([]) ->
                    "share/server/coffee-script.js",
                    "share/server/loop.js"],
 
+    Pre = "(function () {\n",
+    Post = "})();\n",
 
     Concat = fun(Files, To) ->
             AccBin = lists:foldl(fun(Path, Acc) ->
                             {ok, Bin} = file:read_file(Path),
                             [Bin | Acc]
                     end, [], Files),
-            FinalBin = iolist_to_binary(lists:reverse(AccBin)),
+            FinalBin = iolist_to_binary(Pre ++ lists:reverse(AccBin) ++ Post),
             file:write_file(To, FinalBin)
     end,
 


[3/4] couchdb commit: updated refs/heads/master to d6abc18

Posted by rn...@apache.org.
use fresh sandbox for every compile


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/33a71410
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/33a71410
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/33a71410

Branch: refs/heads/master
Commit: 33a71410ea7925ffa2da734e73db460d29f68cf7
Parents: 3841aed
Author: Randall Leeds <ra...@apache.org>
Authored: Sat Feb 20 18:44:16 2016 -0800
Committer: Robert Newson <rn...@apache.org>
Committed: Fri Sep 9 14:10:10 2016 +0100

----------------------------------------------------------------------
 share/server/filter.js |  3 +-
 share/server/loop.js   | 29 +++++------------
 share/server/state.js  |  1 -
 share/server/util.js   | 76 +++++++++++++++++++++------------------------
 4 files changed, 45 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/33a71410/share/server/filter.js
----------------------------------------------------------------------
diff --git a/share/server/filter.js b/share/server/filter.js
index ad29266..ddb6479 100644
--- a/share/server/filter.js
+++ b/share/server/filter.js
@@ -29,8 +29,9 @@ var Filter = (function() {
       },
       filter_view : function(fun, ddoc, args) {
         // recompile
+        var sandbox = create_filter_sandbox();
         var source = fun.toSource ? fun.toSource() : '(' + fun.toString() + ')';
-        fun = evalcx(source, filter_sandbox);
+        fun = evalcx(source, sandbox);
 
         var results = [];
         var docs = args[0];

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33a71410/share/server/loop.js
----------------------------------------------------------------------
diff --git a/share/server/loop.js b/share/server/loop.js
index 1ded19b..f179839 100644
--- a/share/server/loop.js
+++ b/share/server/loop.js
@@ -10,13 +10,10 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-var sandbox = null;
-var filter_sandbox = null;
-
-function init_sandbox() {
+function create_sandbox() {
   try {
     // if possible, use evalcx (not always available)
-    sandbox = evalcx('');
+    var sandbox = evalcx('');
     sandbox.emit = Views.emit;
     sandbox.sum = Views.sum;
     sandbox.log = log;
@@ -29,27 +26,17 @@ function init_sandbox() {
     sandbox.getRow = Render.getRow;
     sandbox.isArray = isArray;
   } catch (e) {
-    //log(e.toSource());
+    var sandbox = {};
   }
+  return sandbox;
 };
-init_sandbox();
 
-function init_filter_sandbox() {
-  try {
-    filter_sandbox = evalcx('');
-    for (var p in sandbox) {
-      if (sandbox.hasOwnProperty(p)) {
-        filter_sandbox[p] = sandbox[p];
-      }
-    }
-    filter_sandbox.emit = Filter.emit;
-  } catch(e) {
-    log(e.toSource ? e.toSource() : e.stack);
-  }
+function create_filter_sandbox() {
+  var sandbox = create_sandbox();
+  sandbox.emit = Filter.emit;
+  return sandbox;
 };
 
-init_filter_sandbox();
-
 // Commands are in the form of json arrays:
 // ["commandname",..optional args...]\n
 //

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33a71410/share/server/state.js
----------------------------------------------------------------------
diff --git a/share/server/state.js b/share/server/state.js
index b8ba046..ff553dd 100644
--- a/share/server/state.js
+++ b/share/server/state.js
@@ -16,7 +16,6 @@ var State = {
     State.funs = [];
     State.lib = null;
     State.query_config = config || {};
-    init_sandbox();
     gc();
     print("true"); // indicates success
   },

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33a71410/share/server/util.js
----------------------------------------------------------------------
diff --git a/share/server/util.js b/share/server/util.js
index 9e49970..e3ea90e 100644
--- a/share/server/util.js
+++ b/share/server/util.js
@@ -61,52 +61,46 @@ var Couch = {
   compileFunction : function(source, ddoc, name) {
     if (!source) throw(["error","not_found","missing function"]);
 
-    var evaluate_function_source = function(source, evalFunction, sandbox) {
-      sandbox = sandbox || {};
-      if(typeof CoffeeScript === "undefined") {
-        return evalFunction(source, sandbox, name);
-      } else {
-        var coffee = CoffeeScript.compile(source, {bare: true});
-        return evalFunction(coffee, sandbox, name);
+    var functionObject = null;
+    var sandbox = create_sandbox();
+
+    var require = function(name, module) {
+      module = module || {};
+      var newModule = resolveModule(name.split('/'), module.parent, ddoc);
+      if (!ddoc._module_cache.hasOwnProperty(newModule.id)) {
+        // create empty exports object before executing the module,
+        // stops circular requires from filling the stack
+        ddoc._module_cache[newModule.id] = {};
+        var s = "function (module, exports, require) { " + newModule.current + "\n }";
+        try {
+          var func = sandbox ? evalcx(s, sandbox, newModule.id) : eval(s);
+          func.apply(sandbox, [newModule, newModule.exports, function(name) {
+            return require(name, newModule);
+          }]);
+        } catch(e) {
+          throw [
+            "error",
+            "compilation_error",
+            "Module require('" +name+ "') raised error " +
+            (e.toSource ? e.toSource() : e.stack)
+          ];
+        }
+        ddoc._module_cache[newModule.id] = newModule.exports;
       }
+      return ddoc._module_cache[newModule.id];
+    };
+
+    if (ddoc) {
+      sandbox.require = require;
+      if (!ddoc._module_cache) ddoc._module_cache = {};
     }
 
     try {
-      if (sandbox) {
-        if (ddoc) {
-          if (!ddoc._module_cache) {
-            ddoc._module_cache = {};
-          }
-          var require = function(name, module) {
-            module = module || {};
-            var newModule = resolveModule(name.split('/'), module.parent, ddoc);
-            if (!ddoc._module_cache.hasOwnProperty(newModule.id)) {
-              // create empty exports object before executing the module,
-              // stops circular requires from filling the stack
-              ddoc._module_cache[newModule.id] = {};
-              var s = "function (module, exports, require) { " + newModule.current + "\n }";
-              try {
-                var func = sandbox ? evalcx(s, sandbox, newModule.id) : eval(s);
-                func.apply(sandbox, [newModule, newModule.exports, function(name) {
-                  return require(name, newModule);
-                }]);
-              } catch(e) { 
-                throw [
-                  "error",
-                  "compilation_error",
-                  "Module require('" +name+ "') raised error " +
-                  (e.toSource ? e.toSource() : e.stack)
-                ];
-              }
-              ddoc._module_cache[newModule.id] = newModule.exports;
-            }
-            return ddoc._module_cache[newModule.id];
-          };
-          sandbox.require = require;
-        }
-        var functionObject = evaluate_function_source(source, evalcx, sandbox);
+      if(typeof CoffeeScript === "undefined") {
+        functionObject = evalcx(source, sandbox, name);
       } else {
-        var functionObject = evaluate_function_source(source, eval);
+        var transpiled = CoffeeScript.compile(source, {bare: true});
+        functionObject = evalcx(transpiled, sandbox, name);
       }
     } catch (err) {
       throw([


[2/4] couchdb commit: updated refs/heads/master to d6abc18

Posted by rn...@apache.org.
seal exposed globals


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/3841aedf
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/3841aedf
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/3841aedf

Branch: refs/heads/master
Commit: 3841aedfb410864b7e7fa4fccbca71afa104bd91
Parents: 4dbd858
Author: Randall Leeds <ra...@apache.org>
Authored: Sat Apr 23 19:32:03 2016 -0700
Committer: Robert Newson <rn...@apache.org>
Committed: Fri Sep 9 14:10:06 2016 +0100

----------------------------------------------------------------------
 share/server/loop.js   | 10 ++++++++++
 share/server/render.js | 43 ++++++++++++++++++++++++++-----------------
 2 files changed, 36 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/3841aedf/share/server/loop.js
----------------------------------------------------------------------
diff --git a/share/server/loop.js b/share/server/loop.js
index 551004a..1ded19b 100644
--- a/share/server/loop.js
+++ b/share/server/loop.js
@@ -165,4 +165,14 @@ var Loop = function() {
   };
 };
 
+// Seal all the globals to prevent modification.
+seal(Couch, true);
+seal(JSON, true);
+seal(Mime, true);
+seal(Render, true);
+seal(Filter, true);
+seal(Views, true);
+seal(isArray, true);
+seal(log, true);
+
 Loop();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/3841aedf/share/server/render.js
----------------------------------------------------------------------
diff --git a/share/server/render.js b/share/server/render.js
index 1fe4da2..946701e 100644
--- a/share/server/render.js
+++ b/share/server/render.js
@@ -57,26 +57,29 @@ var Mime = (function() {
   registerType("url_encoded_form", "application/x-www-form-urlencoded");
   // http://www.ietf.org/rfc/rfc4627.txt
   registerType("json", "application/json", "text/x-json");
-  
-  
+
+
+  var providesUsed = false;
   var mimeFuns = [];
+  var responseContentType = null;
+
   function provides(type, fun) {
-    Mime.providesUsed = true;
+    providesUsed = true;
     mimeFuns.push([type, fun]);
   };
 
   function resetProvides() {
     // set globals
-    Mime.providesUsed = false;
+    providesUsed = false;
     mimeFuns = [];
-    Mime.responseContentType = null;  
+    responseContentType = null;
   };
 
   function runProvides(req, ddoc) {
     var supportedMimes = [], bestFun, bestKey = null, accept = req.headers["Accept"];
     if (req.query && req.query.format) {
       bestKey = req.query.format;
-      Mime.responseContentType = mimesByKey[bestKey][0];
+      responseContentType = mimesByKey[bestKey][0];
     } else if (accept) {
       // log("using accept header: "+accept);
       mimeFuns.reverse().forEach(function(mimeFun) {
@@ -85,12 +88,12 @@ var Mime = (function() {
           supportedMimes = supportedMimes.concat(mimesByKey[mimeKey]);
         }
       });
-      Mime.responseContentType = Mimeparse.bestMatch(supportedMimes, accept);
-      bestKey = keysByMime[Mime.responseContentType];
+      responseContentType = Mimeparse.bestMatch(supportedMimes, accept);
+      bestKey = keysByMime[responseContentType];
     } else {
       // just do the first one
       bestKey = mimeFuns[0][0];
-      Mime.responseContentType = mimesByKey[bestKey][0];
+      responseContentType = mimesByKey[bestKey][0];
     }
 
     if (bestKey) {
@@ -113,12 +116,18 @@ var Mime = (function() {
     }
   };
 
-  
+
   return {
     registerType : registerType,
     provides : provides,
     resetProvides : resetProvides,
-    runProvides : runProvides
+    runProvides : runProvides,
+    providesUsed : function () {
+      return providesUsed;
+    },
+    responseContentType : function () {
+      return responseContentType;
+    }
   };
 })();
 
@@ -145,7 +154,7 @@ var Render = (function() {
   };
 
   function sendStart() {
-    startResp = applyContentType((startResp || {}), Mime.responseContentType);
+    startResp = applyContentType((startResp || {}), Mime.responseContentType());
     respond(["start", chunks, startResp]);
     chunks = [];
     startResp = {};
@@ -155,7 +164,7 @@ var Render = (function() {
   function applyContentType(resp, responseContentType) {
     resp["headers"] = resp["headers"] || {};
     if (responseContentType) {
-      resp["headers"]["Content-Type"] = resp["headers"]["Content-Type"] || responseContentType;    
+      resp["headers"]["Content-Type"] = resp["headers"]["Content-Type"] || responseContentType;
     }
     return resp;
   }
@@ -242,12 +251,12 @@ var Render = (function() {
         resetList();
       }
 
-      if (Mime.providesUsed) {
+      if (Mime.providesUsed()) {
         var provided_resp = Mime.runProvides(args[1], ddoc) || {};
         provided_resp = maybeWrapResponse(provided_resp);
         resp.body = (resp.body || "") + chunks.join("");
         resp.body += provided_resp.body || "";
-        resp = applyContentType(resp, Mime.responseContentType);
+        resp = applyContentType(resp, Mime.responseContentType());
         resetList();
       }
 
@@ -301,9 +310,9 @@ var Render = (function() {
       var req = args[1];
       var tail = listFun.apply(ddoc, args);
 
-      if (Mime.providesUsed) {
+      if (Mime.providesUsed()) {
         tail = Mime.runProvides(req, ddoc);
-      }    
+      }
       if (!gotRow) getRow();
       if (typeof tail != "undefined") {
         chunks.push(tail);


[4/4] couchdb commit: updated refs/heads/master to d6abc18

Posted by rn...@apache.org.
option to disable runtime code evaluation


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/d6abc18f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/d6abc18f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/d6abc18f

Branch: refs/heads/master
Commit: d6abc18f27b7b0d0d6cf3e88d25c8066900958a1
Parents: 33a7141
Author: Randall Leeds <ra...@apache.org>
Authored: Sat Apr 23 17:49:34 2016 -0700
Committer: Robert Newson <rn...@apache.org>
Committed: Fri Sep 9 14:27:56 2016 +0100

----------------------------------------------------------------------
 rebar.config.script                      |  2 +-
 test/javascript/tests/view_sandboxing.js | 41 +++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/d6abc18f/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index cece0f9..104006e 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -29,7 +29,7 @@ DepDescs = [
 {b64url,           "b64url",           "6895652d80f95cdf04efb14625abed868998f174"},
 {couch_log,        "couch-log",        "ad803f66dbd1900b67543259142875a6d03503ce"},
 {chttpd,           "chttpd",           "c6b044006fcb58386099105fb6d9e0a036a62ed9"},
-{couch,            "couch",            "72869b8bf139ffc2542d02a2bd3b862042a668c3"},
+{couch,            "couch",            "092dec86bbf068e0ab99f6586668260515fc86a9"},
 {couch_index,      "couch-index",      "53555fd909d5dd3d4a610c3fd6795950a8f7d022"},
 {couch_mrview,     "couch-mrview",     "a0b0392afe66ece9ef3bb4fdd5a4f159c97c47eb"},
 {couch_replicator, "couch-replicator", "b9232c8d410d529d65030896e075c4b4327631b0"},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d6abc18f/test/javascript/tests/view_sandboxing.js
----------------------------------------------------------------------
diff --git a/test/javascript/tests/view_sandboxing.js b/test/javascript/tests/view_sandboxing.js
index c70eecc..171777b 100644
--- a/test/javascript/tests/view_sandboxing.js
+++ b/test/javascript/tests/view_sandboxing.js
@@ -145,6 +145,47 @@ couchTests.view_sandboxing = function(debug) {
   }
 */
 
+  // test that runtime code evaluation can be prevented
+  console.log('TODO: config port not available on cluster');
+  /*var couchjs_command_xhr = CouchDB.request(
+    "GET", "/_config/query_servers/javascript");
+
+  var couchjs_command = JSON.parse(couchjs_command_xhr.responseText);
+  var couchjs_command_args = couchjs_command.match(/\S+|"(?:\\"|[^"])+"/g);
+
+  couchjs_command_args.splice(1, 0, "--no-eval");
+  var new_couchjs_command = couchjs_command_args.join(" ");
+
+  run_on_modified_server(
+    [{section: "query_servers",
+      key: "javascript",
+      value: new_couchjs_command}],
+    function () {
+      var ddoc = {
+        _id: "_design/foobar",
+        language: "javascript",
+        views: {
+          view: {
+            map:
+            (function(doc) {
+              var glob = emit.constructor('return this')();
+              emit(doc._id, null);
+            }).toString()
+          }
+        }
+      };
+
+      db.deleteDb();
+      db.createDb();
+      T(db.save(ddoc).ok);
+
+      T(db.save(doc).ok);
+      var results = db.view(
+        "foobar/view", {bypass_cache: Math.round(Math.random() * 1000)});
+
+      TEquals(0, results.rows.length);
+    });*/
+
   // cleanup
   db.deleteDb();
 };