Issue #2060 Disallow uppercase radix prefixes and exponential notation

This commit is contained in:
Gerald Lewis 2012-01-20 17:23:50 -05:00
parent 8ac440fd52
commit 34e517de09
3 changed files with 30 additions and 19 deletions

View File

@ -109,19 +109,23 @@
};
Lexer.prototype.numberToken = function() {
var binaryLiteral, dec, lexedLength, match, nonStrictOctalLiteral, number, oct, octalLiteral;
var binaryLiteral, lexedLength, match, number, octalLiteral;
if (!(match = NUMBER.exec(this.chunk))) return 0;
number = match[0];
lexedLength = number.length;
if (nonStrictOctalLiteral = /^0\d+/.test(number)) {
dec = /[89]/.test(number) ? "\"" + number + "\" " : '';
oct = dec ? '' : "\"" + number + "\" ";
this.error("decimal literals " + dec + "must not be prefixed with '0'; octal literals " + oct + "must be prefixed with '0o'");
if (/[E]/.test(number)) {
this.error("exponential notation must be indicated with a lowercase 'e'");
} else if (/[BOX]/.test(number)) {
this.error("radix prefixes must be lowercase '" + number + "'");
} else if (/^0[89]/.test(number)) {
this.error("decimal literals '" + number + "' must not be prefixed with '0'");
} else if (/^0[0-7]/.test(number)) {
this.error("octal literals '" + number + "' must be prefixed with '0o'");
}
if (octalLiteral = /0o([0-7]+)/i.exec(number)) {
lexedLength = number.length;
if (octalLiteral = /0o([0-7]+)/.exec(number)) {
number = (parseInt(octalLiteral[1], 8)).toString();
}
if (binaryLiteral = /0b([01]+)/i.exec(number)) {
if (binaryLiteral = /0b([01]+)/.exec(number)) {
number = (parseInt(binaryLiteral[1], 2)).toString();
}
this.token('NUMBER', number);
@ -645,7 +649,7 @@
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
NUMBER = /^0x[\da-f]+|^0b[01]+|^0o[0-7]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;

View File

@ -133,14 +133,18 @@ exports.Lexer = class Lexer
numberToken: ->
return 0 unless match = NUMBER.exec @chunk
number = match[0]
if /[E]/.test number
@error "exponential notation must be indicated with a lowercase 'e'"
else if /[BOX]/.test number
@error "radix prefixes must be lowercase '#{number}'"
else if /^0[89]/.test number
@error "decimal literals '#{number}' must not be prefixed with '0'"
else if /^0[0-7]/.test number
@error "octal literals '#{number}' must be prefixed with '0o'"
lexedLength = number.length
if nonStrictOctalLiteral = /^0\d+/.test number
dec = if /[89]/.test number then "\"#{number}\" " else ''
oct = if dec then '' else "\"#{number}\" "
@error "decimal literals #{dec}must not be prefixed with '0'; octal literals #{oct}must be prefixed with '0o'"
if octalLiteral = /0o([0-7]+)/i.exec number
if octalLiteral = /0o([0-7]+)/.exec number
number = (parseInt octalLiteral[1], 8).toString()
if binaryLiteral = /0b([01]+)/i.exec number
if binaryLiteral = /0b([01]+)/.exec number
number = (parseInt binaryLiteral[1], 2).toString()
@token 'NUMBER', number
lexedLength
@ -596,9 +600,9 @@ IDENTIFIER = /// ^
///
NUMBER = ///
^ 0x[\da-f]+ | # hex
^ 0b[01]+ | # binary
^ 0o[0-7]+ | # octal
^ 0x[\da-f]+ | # hex
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
///i

View File

@ -15,7 +15,6 @@
test "Parser recognises binary numbers", ->
eq 4, 0b100
eq 5, 0B101
# Decimal Integer Literals
@ -57,12 +56,16 @@ test '#1168: leading floating point suppresses newline', ->
test "Python-style octal literal notation '0o777'", ->
eq 511, 0o777
eq 511, 0O777
eq 1, 0o1
eq 1, 0O1
eq 1, 0o00001
eq parseInt('0777', 8), 0o777
eq '777', 0o777.toString 8
eq 4, 0o4.valueOf()
eq Number::toString, 0o777['toString']
eq Number::toString, 0o777.toString
test "#2060: Disallow uppercase radix prefixes and exponential notation", ->
for char in ['b', 'o', 'x', 'e']
program = "0#{char}0"
doesNotThrow -> CoffeeScript.compile program, bare: yes
throws -> CoffeeScript.compile program.toUpperCase(), bare: yes