Clone various parameter lists in livedata

Specifically:

 - On client, clone parameters to sub and methods (so that if they're
   modified outside before the method message is actually sent, before
   the sub params are used for de-duping, or before resending messages
   on reconnect, this doesn't affect what we do)
 - On server, ensure that method bodies mutating their arguments does
   not affect callers of Meteor.call (executing locally)

Fixes #2025.
This commit is contained in:
David Glasser
2014-04-10 14:48:29 -07:00
parent f63aeee8eb
commit e91713d909
2 changed files with 8 additions and 2 deletions

View File

@@ -519,7 +519,7 @@ _.extend(Connection.prototype, {
self._subscriptions[id] = {
id: id,
name: name,
params: params,
params: EJSON.clone(params),
inactive: false,
ready: false,
readyDeps: (typeof Deps !== "undefined") && new Deps.Dependency,
@@ -644,6 +644,10 @@ _.extend(Connection.prototype, {
);
}
// Keep our args safe from mutation (eg if we don't send the message for a
// while because of a wait method).
args = EJSON.clone(args);
// Lazily allocate method ID once we know that it'll be needed.
var methodId = (function () {
var id;
@@ -691,6 +695,7 @@ _.extend(Connection.prototype, {
// Because saveOriginals and retrieveOriginals aren't reentrant,
// don't allow stubs to yield.
return Meteor._noYieldsAllowed(function () {
// re-clone, so that the stub can't affect our caller's values
return stub.apply(invocation, EJSON.clone(args));
});
} else {

View File

@@ -1399,7 +1399,8 @@ _.extend(Server.prototype, {
try {
var result = DDP._CurrentInvocation.withValue(invocation, function () {
return maybeAuditArgumentChecks(
handler, invocation, args, "internal call to '" + name + "'");
handler, invocation, EJSON.clone(args), "internal call to '" +
name + "'");
});
} catch (e) {
exception = e;