shithub: libmujs

Download patch

ref: dbeda99b66672d098c42f0d231a89a4288ad3a7d
parent: 581412fba531601c7232bfff0e371c7471ca2c04
author: Tor Andersson <tor.andersson@gmail.com>
date: Mon Apr 3 08:09:14 EDT 2017

Fix JSON number parsing.

We were using too relaxed number parsing rules, and we didn't support
an initial sign character.

Also detect missing exponent in regular number parsing.

--- a/jslex.c
+++ b/jslex.c
@@ -353,8 +353,11 @@
 	if (jsY_accept(J, 'e') || jsY_accept(J, 'E')) {
 		if (J->lexchar == '-' || J->lexchar == '+')
 			jsY_next(J);
-		while (jsY_isdec(J->lexchar))
-			jsY_next(J);
+		if (jsY_isdec(J->lexchar))
+			while (jsY_isdec(J->lexchar))
+				jsY_next(J);
+		else
+			jsY_error(J, "missing exponent");
 	}
 
 	if (jsY_isidentifierstart(J->lexchar))
@@ -362,7 +365,6 @@
 
 	J->number = js_strtod(s, NULL);
 	return TK_NUMBER;
-
 }
 
 #endif
@@ -723,6 +725,43 @@
 	return J->lasttoken = jsY_lexx(J);
 }
 
+static int lexjsonnumber(js_State *J)
+{
+	const char *s = J->source - 1;
+
+	if (J->lexchar == '-')
+		jsY_next(J);
+
+	if (J->lexchar == '0')
+		jsY_next(J);
+	else if (J->lexchar >= '1' && J->lexchar <= '9')
+		while (isdigit(J->lexchar))
+			jsY_next(J);
+	else
+		jsY_error(J, "unexpected non-digit");
+	if (jsY_accept(J, '.'))
+	{
+		if (isdigit(J->lexchar))
+			while (isdigit(J->lexchar))
+				jsY_next(J);
+		else
+			jsY_error(J, "missing digits after decimal point");
+	}
+
+	if (jsY_accept(J, 'e') || jsY_accept(J, 'E')) {
+		if (J->lexchar == '-' || J->lexchar == '+')
+			jsY_next(J);
+		if (isdigit(J->lexchar))
+			while (isdigit(J->lexchar))
+				jsY_next(J);
+		else
+			jsY_error(J, "missing digits after exponent indicator");
+	}
+
+	J->number = js_strtod(s, NULL);
+	return TK_NUMBER;
+}
+
 int jsY_lexjson(js_State *J)
 {
 	while (1) {
@@ -731,9 +770,8 @@
 		while (jsY_iswhite(J->lexchar) || J->lexchar == '\n')
 			jsY_next(J);
 
-		if (J->lexchar >= '0' && J->lexchar <= '9') {
-			return lexnumber(J);
-		}
+		if ((J->lexchar >= '0' && J->lexchar <= '9') || J->lexchar == '-')
+			return lexjsonnumber(J);
 
 		switch (J->lexchar) {
 		case ',': jsY_next(J); return ',';
@@ -745,9 +783,6 @@
 
 		case '"':
 			return lexstring(J);
-
-		case '.':
-			return lexnumber(J);
 
 		case 'f':
 			jsY_next(J); jsY_expect(J, 'a'); jsY_expect(J, 'l'); jsY_expect(J, 's'); jsY_expect(J, 'e');