forked from mongodb/mongo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjs_scope_leak.js
107 lines (89 loc) · 3.23 KB
/
js_scope_leak.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
* @tags: [
* requires_scripting
* ]
*/
// Test for SERVER-9129
// Verify global scope data does not persist past logout or auth.
// NOTE: Each test case covers 3 state transitions:
// no auth -> auth user 'a'
// auth user 'a' -> auth user 'b'
// auth user 'b' -> logout
//
// These transitions are tested for $where and MapReduce.
const conn = MongoRunner.runMongod();
const test = conn.getDB("test");
// insert a single document and add two test users
assert.writeOK(test.foo.insert({a: 1}));
assert.eq(1, test.foo.findOne().a);
test.createUser({user: 'a', pwd: 'a', roles: jsTest.basicUserRoles});
test.createUser({user: 'b', pwd: 'b', roles: jsTest.basicUserRoles});
function missingOrEquals(string) {
return 'function() { ' +
'var global = function(){return this;}.call();'
// Uncomment the next line when debugging.
// + 'print(global.hasOwnProperty("someGlobal") ? someGlobal : "MISSING" );'
+ 'return !global.hasOwnProperty("someGlobal")' +
' || someGlobal == unescape("' + escape(string) + '");' +
'}()';
}
// test $where
function testWhere() {
// set the global variable 'someGlobal' before authenticating
test.foo.findOne({$where: 'someGlobal = "noUsers";'});
// test new user auth causes scope to be cleared
assert(test.auth('a', 'a'));
assert.eq(
1, test.foo.count({$where: 'return ' + missingOrEquals('a')}), "$where: Auth user 'a");
// test auth as another user causes scope to be cleared
test.foo.findOne({$where: 'someGlobal = "a";'});
test.logout();
test.auth('b', 'b');
assert(test.foo.count({$where: 'return ' + missingOrEquals('a&b')}), "$where: Auth user 'b'");
// test user logout causes scope to be cleared
test.foo.findOne({$where: 'someGlobal = "a&b";'});
test.logout();
assert(test.foo.count({$where: 'return ' + missingOrEquals('noUsers')}), "$where: log out");
}
testWhere();
testWhere();
function testMapReduce() {
function mapSet(string) {
return Function('someGlobal = "' + string + '"');
}
function mapGet(string) {
return Function('assert(' + missingOrEquals(string) + ')');
}
function reduce(k, v) {
// Do nothing
}
function setGlobalInMap(string) {
test.foo.mapReduce(mapSet(string), reduce, {out: {inline: 1}});
}
function getGlobalFromMap(string) {
test.foo.mapReduce(mapGet(string), reduce, {out: {inline: 1}});
}
// set the global variable 'someGlobal' before authenticating
setGlobalInMap('noUsers');
// test new user auth causes scope to be cleared
assert(test.auth('a', 'a'));
assert.doesNotThrow(function() {
getGlobalFromMap('a');
}, [], "M/R: Auth user 'a'");
// test auth as another user causes scope to be cleared
setGlobalInMap('a');
test.logout();
assert(test.auth('b', 'b'));
assert.doesNotThrow(function() {
getGlobalFromMap('a&b');
}, [], "M/R: Auth user 'b'");
// test user logout causes scope to be cleared
setGlobalInMap('a&b');
test.logout();
assert.doesNotThrow(function() {
getGlobalFromMap('noUsers');
}, [], "M/R: Log out");
}
testMapReduce();
testMapReduce();
MongoRunner.stopMongod(conn);