Skip to content

Commit 806da34

Browse files
committed
Generate placeholder regexp with a uid for safety
Fixes yahoo#5
1 parent 826a981 commit 806da34

File tree

1 file changed

+17
-16
lines changed

1 file changed

+17
-16
lines changed

index.js

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ See the accompanying LICENSE file for terms.
88

99
var isRegExp = require('util').isRegExp;
1010

11-
module.exports = serialize;
11+
// Generate an internal UID to make the regexp pattern harder to guess.
12+
var UID = Math.floor(Math.random() * 0x10000000000).toString(16);
13+
var PLACE_HOLDER_REGEXP = new RegExp('"@__(FUNCTION|REGEXP)-' + UID + '-(\\d+)__@"', 'g');
1214

13-
var IS_NATIVE_CODE_REGEX = /\{\s*\[native code\]\s*\}/g,
14-
PLACE_HOLDER_REGEX = /"@__(FUNCTION|REGEXP)_(\d+)__@"/g,
15-
UNSAFE_CHARS_REGEX = /[<>\/\u2028\u2029]/g;
15+
var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
16+
var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
1617

1718
// Mapping of unsafe HTML and invalid JavaScript line terminator chars to their
1819
// Unicode char counterparts which are safe to use in JavaScript strings.
@@ -31,21 +32,21 @@ var UNICODE_CHARS = {
3132
// `JSON.stringify()` `space` option to a truthy value.
3233
var SPACE = 2;
3334

34-
function serialize(obj) {
35-
var functions = [],
36-
regexps = [],
37-
str;
35+
module.exports = function serialize(obj) {
36+
var functions = [];
37+
var regexps = [];
38+
var str;
3839

3940
// Creates a JSON string representation of the object and uses placeholders
4041
// for functions and regexps (identified by index) which are later
4142
// replaced.
4243
str = JSON.stringify(obj, function (key, value) {
4344
if (typeof value === 'function') {
44-
return '@__FUNCTION_' + (functions.push(value) - 1) + '__@';
45+
return '@__FUNCTION-' + UID + '-' + (functions.push(value) - 1) + '__@';
4546
}
4647

4748
if (typeof value === 'object' && isRegExp(value)) {
48-
return '@__REGEXP_' + (regexps.push(value) - 1) + '__@';
49+
return '@__REGEXP-' + UID + '-' + (regexps.push(value) - 1) + '__@';
4950
}
5051

5152
return value;
@@ -60,7 +61,7 @@ function serialize(obj) {
6061
// Replace unsafe HTML and invalid JavaScript line terminator chars with
6162
// their safe Unicode char counterpart. This _must_ happen before the
6263
// regexps and functions are serialized and added back to the string.
63-
str = str.replace(UNSAFE_CHARS_REGEX, function (unsafeChar) {
64+
str = str.replace(UNSAFE_CHARS_REGEXP, function (unsafeChar) {
6465
return UNICODE_CHARS[unsafeChar];
6566
});
6667

@@ -71,15 +72,15 @@ function serialize(obj) {
7172
// Replaces all occurrences of function and regexp placeholders in the JSON
7273
// string with their string representations. If the original value can not
7374
// be found, then `undefined` is used.
74-
return str.replace(PLACE_HOLDER_REGEX, function (match, type, index) {
75+
return str.replace(PLACE_HOLDER_REGEXP, function (match, type, valueIndex) {
7576
if (type === 'REGEXP') {
76-
return regexps[index].toString();
77+
return regexps[valueIndex].toString();
7778
}
7879

79-
var fn = functions[index],
80-
serializedFn = fn.toString();
80+
var fn = functions[valueIndex];
81+
var serializedFn = fn.toString();
8182

82-
if (IS_NATIVE_CODE_REGEX.test(serializedFn)) {
83+
if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) {
8384
throw new TypeError('Serializing native function: ' + fn.name);
8485
}
8586

0 commit comments

Comments
 (0)