[tarantool-patches] [PATCH] lua: fix tonumber64() for strings containing "ULL"

Serge Petrenko sergepetrenko at tarantool.org
Tue Nov 20 16:39:58 MSK 2018


tonumber64() doesn't understand strings with "ULL" like "123ULL". The
expected output for tonumber64("123ULL") is 123, since 123ULL is a
correct number notation in lua. However, our function returns null.
This happens because suffix isn't trimmed in tonumber64.

Trim ULL/LLU, LL suffixes, but only when no base is specified or
base is equal to either 2, 10 or 16.

Part of #3431
---
https://github.com/tarantool/tarantool/tree/sp/gh-3431-tonumber-with-ull
https://github.com/tarantool/tarantool/issues/3431

 src/lua/init.c         | 29 +++++++++++++++++++++++++++--
 test/box/misc.result   | 19 +++++++++++++++++++
 test/box/misc.test.lua |  8 ++++++++
 3 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/src/lua/init.c b/src/lua/init.c
index 07bcca1b9..ae5bb4ba7 100644
--- a/src/lua/init.c
+++ b/src/lua/init.c
@@ -199,6 +199,10 @@ lbox_tonumber64(struct lua_State *L)
 		 * 1) '0x' or '0X' trim in case of base == 16 or base == -1
 		 * 2) '0b' or '0B' trim in case of base == 2  or base == -1
 		 * 3) '-' for negative numbers
+		 * 4) LL, ULL, LLU - trim, but only for base == 2 or
+		 *    base == 16 or base == -1. For consistency do not bother
+		 *    with any non-common bases, since user may have specified
+		 *    base >= 22, in which case 'L' will be a digit.
 		 */
 		char negative = 0;
 		if (arg[0] == '-') {
@@ -214,7 +218,26 @@ lbox_tonumber64(struct lua_State *L)
 				base = 2;  arg += 2; argl -= 2;
 			}
 		}
-		base = (base == -1 ? 10 : base);
+		bool ull = false;
+		if (argl > 2 && (base == 2 || base == 16 || base == -1)) {
+			if (arg[argl - 1] == 'u' || arg[argl - 1] == 'U') {
+				ull = true;
+				--argl;
+			}
+			if ((arg[argl - 1] == 'l' || arg[argl - 1] == 'L') &&
+			    (arg[argl - 2] == 'l' || arg[argl - 2] == 'L'))
+				argl -= 2;
+			else {
+				ull = false;
+				goto skip;
+			}
+			if (!ull && (arg[argl - 1] == 'u' ||
+				     arg[argl - 1] == 'U')) {
+				ull = true;
+				--argl;
+			}
+		}
+skip:		base = (base == -1 ? 10 : base);
 		errno = 0;
 		char *arge;
 		unsigned long long result = strtoull(arg, &arge, base);
@@ -231,7 +254,9 @@ lbox_tonumber64(struct lua_State *L)
 				 * Finally,
 				 *  result - 1 > INT64_MAX;
 				 */
-				if (result != 0 && result - 1 > INT64_MAX)
+				if (ull)
+					luaL_pushuint64(L, (UINT64_MAX - result) + 1);
+				else if (result != 0 && result - 1 > INT64_MAX)
 					lua_pushnil(L);
 				else
 					luaL_pushint64(L, -result);
diff --git a/test/box/misc.result b/test/box/misc.result
index 4ee4797d0..19554b62d 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -655,6 +655,25 @@ tostring(tonumber64('0')) == '0'
 ---
 - true
 ...
+--
+-- gh-3431: tonumber of strings with ULL.
+--
+tonumber64('-1ULL') == -1ULL
+---
+- true
+...
+tonumber64('-1LL') == -1LL
+---
+- true
+...
+tonumber64('12345678910ULL') == 12345678910ULL
+---
+- true
+...
+tonumber64(tostring(tonumber64('1234567890123456'))) == 1234567890123456ULL
+---
+- true
+...
 tonumber64('0x12') == 18
 ---
 - true
diff --git a/test/box/misc.test.lua b/test/box/misc.test.lua
index ee81c7be1..d799088d2 100644
--- a/test/box/misc.test.lua
+++ b/test/box/misc.test.lua
@@ -173,6 +173,14 @@ tostring(tonumber64('-9223372036854775808')) == '-9223372036854775808LL'
 tonumber64('-9223372036854775809') == nil
 tostring(tonumber64('0')) == '0'
 
+--
+-- gh-3431: tonumber of strings with ULL.
+--
+tonumber64('-1ULL') == -1ULL
+tonumber64('-1LL') == -1LL
+tonumber64('12345678910ULL') == 12345678910ULL
+tonumber64(tostring(tonumber64('1234567890123456'))) == 1234567890123456ULL
+
 tonumber64('0x12') == 18
 tonumber64('0x12', 16) == 18
 tonumber64('0x12', 17) == nil
-- 
2.17.2 (Apple Git-113)





More information about the Tarantool-patches mailing list