2011/6/15 Gareth <[email protected]>:
> It's a nice idea but within the constructor call you are using a
> regular expression literal, you'd have to watch out for IE quirks (if
> you're supporting it) in regex parsing. For example:-
> /[^]/]/,alert(1)
Good point. I knew that [^] as a better way of saying any character
doesn't work on IE but didn't know why.
To avoid this, we could disallow any regular expression literals
controlled by an attacker in the output by replacing
/foo/i
with
/./.constructor("foo", "i")
Still a token-level transformation.
> On Jun 15, 12:37 am, Mike Samuel <[email protected]> wrote:
>> We have a very good regular lexical grammar that approximates the way
>> JavaScript interpreters tokenize JavaScript source, but we rely on our
>> source tree rendering to make sure that a JavaScript interpreter will
>> always come to the same conclusion as to where regular expression
>> literals and division operators start and end.
>>
>> SES might benefit from a cheap reliable transformation that
>> (1) takes a string of SES source
>> (2) produces a string of SES source where a standards compliant
>> JavaScript interpreter will either throw a ParseError or come to the
>> same conclusion as an approximate regular lexical grammar
>>
>> I think the below is such a transformation.
>>
>> function removeSlashAmbiguity(tokens /* []string */) {
>> var outputTokens = [];
>> for (var i = 0, n = tokens.length; i < n; ++i) {
>> var token = tokens[i];
>> if (isRegularExpressionToken(token)) {
>> outputTokens.push("/./", ".", "constructor", "(", token, ")");
>> } else if (token === "/" || token === "/=") {
>> outputTokens.push(token.replace(/^\//, "*"), "1", "*");
>> } else {
>> outputTokens.push(token);
>> }
>> }
>> return outputTokens;
>>
>> }
>>
>> To break it down:
>>
>> (1) a regular expression /foo/i is transformed to
>> /./.constructor(/foo/i)
>>
>> If the "/" at the start of /foo/i were a division operator, then
>> the transformed code would fail to parse because of the dot in
>> /./.
>>
>> This is valid because the dot operator and the function call
>> operator bind very tightly.
>>
>> It is semantics preserving because /./.constructor is a reliably
>> path (in SES) to RegExp and RegExp(/./) returns its input
>> unchanged.
>>
>> It also does not conflict with semicolon insertion -- there is no
>> infix operator on the left (or ParseError would have been thrown)
>> that might attach to the previous line.
>>
>> (2) A use of the division operator (a / b) is transformed to (a * 1 / b)
>>
>> If our lexing was wrong and the slash was the start of a regular
>> expression, then replacing the slash with an asterisk makes the
>> content obviously a numeric operation, so our interpretation is
>> maintained.
>>
>> This is semantics preserving because both * and / coerce both
>> sides to numbers, and have the same precedence, and 1 is
>> multiplicative identity.
>>
>> (3) A use of the /= operator (a /= b) is transformed to (a *= 1 / b)
>>
>> Same argument as 2.
>>
>> This is semantics preserving because the left-hand side is
>> unchanged and is evaluated only once, and same argument as 2.