json2.js
Today I attended Wakate IT Benkyou-kai (in English, "Young IT Study Meetup"?). We read Secrets of the JavaScript Ninja and today's chapter is "Code Evaluation". This book contains many real-world examples. We saw Caja, Prototype, json2.js, base2, Packer, Screw.Unit, Processing.js and Objective-J.
For me, today's most striking code is json2.js. It has eval-based JSON parser and prevent unsafe code evaluation by an regular expression. (Note: real code is well-commented. You can see it at GitHub.)
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
j = eval('(' + text + ')');
Huh?
Okay, let's try on WebKit's console. First pattern works like so:
> '{ "key": ["value\\n"] }'
"{ "key": ["value\n"] }"
> '{ "key": ["value\\n"] }'.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
"{ "key": ["value@"] }"
Second pattern works like so:
> '{ "key": ["value@"] }'.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
"{ ]: []] }"
Third pattern works like so:
> "{ ]: []] }".replace(/(?:^|:|,)(?:\s*\[)+/g, '')
"{ ]]] }"
Last but not least, can it be matched with /^[\],:{}\s]*$/?
> /^[\],:{}\s]*$/.test('{ ]]] }')
true
Great! We can pass the original string to eval() safely.
json2.js is implemented by Douglas Crockford, the designer of JSON. However, if I design JSON, I can't implement my safety checker like Douglas's. I'm not Chuck Norris.