diff mbox series

[OpenWrt-Devel] lua: lnum: fix strtoul based number parsing

Message ID 1558043563-10184-1-git-send-email-ynezz@true.cz
State Accepted, archived
Delegated to: Petr Štetiar
Headers show
Series [OpenWrt-Devel] lua: lnum: fix strtoul based number parsing | expand

Commit Message

Petr Štetiar May 16, 2019, 9:52 p.m. UTC
From: Liangbin Lian <jjm2473@gmail.com>

Lua's LNUM patch currently doesn't parse properly certain numbers as
it's visible from the following simple tests.

On x86_64 host (stock Lua 5.1.5, expected output):

 $ /usr/bin/lua -e 'print(0x80000000); print(0x80000000000); print(0x100000000)'

  2147483648
  8796093022208
  4294967296

On x86_64 host:

 $ staging_dir/hostpkg/bin/lua -e 'print(0x80000000); print(0x80000000000); print(0x100000000)'

  -2147483648
  0
  0

On x86_64 target:

 $ lua -e 'print(0x80000000); print(0x80000000000); print(0x100000000)'

  -2147483648
  0
  0

On ath79 target:

 $ lua -e 'print(0x80000000); print(0x80000000000); print(0x100000000)'

  -2147483648
  8796093022208
  4294967296

It's caused by two issues fixed in this patch, first issue is caused by
unhadled strtoul overflow and second one is caused by the cast of
unsigned to signed Lua integer when parsing from hex literal.

Run tested on:

 * Zidoo Z9S with RTD1296 CPU (aarch64_cortex-a53)
 * qemu/x86_64
 * qemu/armvirt_64
 * ath79

Signed-off-by: Liangbin Lian <jjm2473@gmail.com>
[commit subject/message touches, fixed From to match SOB, fixed another
 unhandled case in luaO_str2i, host Lua, package bump]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---

 This patch originated in https://github.com/openwrt/openwrt/pull/2067 and I'm
 sending it for the review and testing to the mailing list as well, since I
 consider Lua as a core building block, so the more eyes, the better.

 package/utils/lua/Makefile                         |  2 +-
 .../013-lnum-strtoul-parsing-fixes.patch           | 48 ++++++++++++++++++++++
 .../patches/013-lnum-strtoul-parsing-fixes.patch   | 48 ++++++++++++++++++++++
 3 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch
 create mode 100644 package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch

Comments

Karl Palsson May 21, 2019, 10:01 a.m. UTC | #1
Petr Štetiar  <ynezz@true.cz> wrote:
> From: Liangbin Lian <jjm2473@gmail.com>
> 
> Lua's LNUM patch currently doesn't parse properly certain
> numbers as it's visible from the following simple tests.
> 


Tested-by: Karl Palsson <karlp@etactica.com>

This makes some busted unit tests of ours pass for the first time
on the openwrt target itself :) It will also mean we can drop
some places where we use "0x40000000 * 2" instead of the more
understandable 0x80000000 form :) (We've had problems with lnum
and reading arrays of 16bit numbers into various 32bit
singed/unsigned floating point forms in the past)

Sincerely,
Karl Palsson
diff mbox series

Patch

diff --git a/package/utils/lua/Makefile b/package/utils/lua/Makefile
index c34e569b67a7..077a60fbf3e8 100644
--- a/package/utils/lua/Makefile
+++ b/package/utils/lua/Makefile
@@ -9,7 +9,7 @@  include $(TOPDIR)/rules.mk
 
 PKG_NAME:=lua
 PKG_VERSION:=5.1.5
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://www.lua.org/ftp/ \
diff --git a/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch b/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch
new file mode 100644
index 000000000000..7f00c8c3a2df
--- /dev/null
+++ b/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch
@@ -0,0 +1,48 @@ 
+diff --git a/src/lnum.c b/src/lnum.c
+index 1456b6a2ed23..b0632b04c2b7 100644
+--- a/src/lnum.c
++++ b/src/lnum.c
+@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
+ #else
+       return 0;  /* Reject the number */
+ #endif
++    } else if (v > LUA_INTEGER_MAX) {
++      return TK_NUMBER;
+     }
+   } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
+     return TK_NUMBER;	/* not in signed range, or has '.', 'e' etc. trailing */
+@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Integer ib ) {
+   return 0;
+ }
+ 
++#ifdef LONG_OVERFLOW_LUA_INTEGER
++unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base ) {
++  unsigned long v= strtoul(str, endptr, base);
++  if ( v > LUA_INTEGER_MAX ) {
++    errno= ERANGE;
++    v= ULONG_MAX;
++  }
++  return (unsigned LUA_INTEGER)v;
++}
++#endif
+diff --git a/src/lnum_config.h b/src/lnum_config.h
+index 19d7a4231a49..1092eead6629 100644
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -141,7 +141,12 @@
+ #endif
+ 
+ #ifndef lua_str2ul
+-# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# if LONG_MAX > LUA_INTEGER_MAX
++#   define LONG_OVERFLOW_LUA_INTEGER
++    unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base );
++# else
++#  define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# endif
+ #endif
+ #ifndef LUA_INTEGER_MIN
+ # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1)  /* -2^16|32 */
+-- 
+1.9.1
+
diff --git a/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch b/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch
new file mode 100644
index 000000000000..7f00c8c3a2df
--- /dev/null
+++ b/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch
@@ -0,0 +1,48 @@ 
+diff --git a/src/lnum.c b/src/lnum.c
+index 1456b6a2ed23..b0632b04c2b7 100644
+--- a/src/lnum.c
++++ b/src/lnum.c
+@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
+ #else
+       return 0;  /* Reject the number */
+ #endif
++    } else if (v > LUA_INTEGER_MAX) {
++      return TK_NUMBER;
+     }
+   } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
+     return TK_NUMBER;	/* not in signed range, or has '.', 'e' etc. trailing */
+@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Integer ib ) {
+   return 0;
+ }
+ 
++#ifdef LONG_OVERFLOW_LUA_INTEGER
++unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base ) {
++  unsigned long v= strtoul(str, endptr, base);
++  if ( v > LUA_INTEGER_MAX ) {
++    errno= ERANGE;
++    v= ULONG_MAX;
++  }
++  return (unsigned LUA_INTEGER)v;
++}
++#endif
+diff --git a/src/lnum_config.h b/src/lnum_config.h
+index 19d7a4231a49..1092eead6629 100644
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -141,7 +141,12 @@
+ #endif
+ 
+ #ifndef lua_str2ul
+-# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# if LONG_MAX > LUA_INTEGER_MAX
++#   define LONG_OVERFLOW_LUA_INTEGER
++    unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base );
++# else
++#  define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# endif
+ #endif
+ #ifndef LUA_INTEGER_MIN
+ # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1)  /* -2^16|32 */
+-- 
+1.9.1
+