Skip to content

Commit f3cf0d6

Browse files
author
Mike Pall
committed
Give expected results for negative non-base-10 numbers in tonumber().
This was undefined in Lua 5.1, but it's defined in 5.2.
1 parent fe651bf commit f3cf0d6

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

src/lib_base.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -287,18 +287,27 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
287287
} else {
288288
const char *p = strdata(lj_lib_checkstr(L, 1));
289289
char *ep;
290+
unsigned int neg = 0;
290291
unsigned long ul;
291292
if (base < 2 || base > 36)
292293
lj_err_arg(L, 2, LJ_ERR_BASERNG);
293-
ul = strtoul(p, &ep, base);
294-
if (p != ep) {
295-
while (lj_char_isspace((unsigned char)(*ep))) ep++;
296-
if (*ep == '\0') {
297-
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u))
298-
setintV(L->base-1-LJ_FR2, (int32_t)ul);
299-
else
300-
setnumV(L->base-1-LJ_FR2, (lua_Number)ul);
301-
return FFH_RES(1);
294+
while (lj_char_isspace((unsigned char)(*p))) p++;
295+
if (*p == '-') { p++; neg = 1; } else if (*p == '+') { p++; }
296+
if (lj_char_isalnum((unsigned char)(*p))) {
297+
ul = strtoul(p, &ep, base);
298+
if (p != ep) {
299+
while (lj_char_isspace((unsigned char)(*ep))) ep++;
300+
if (*ep == '\0') {
301+
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) {
302+
if (neg) ul = -ul;
303+
setintV(L->base-1-LJ_FR2, (int32_t)ul);
304+
} else {
305+
lua_Number n = (lua_Number)ul;
306+
if (neg) n = -n;
307+
setnumV(L->base-1-LJ_FR2, n);
308+
}
309+
return FFH_RES(1);
310+
}
302311
}
303312
}
304313
}

0 commit comments

Comments
 (0)