diff options
| author | Mike Pall <mike> | 2010-05-20 00:40:51 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-05-20 00:40:51 +0200 |
| commit | 926f688cd0cc177a779ee3bdb2c6a346383dd8e4 (patch) | |
| tree | d9539304a9f0d8cf1b8fd47d6252de6bfbe75b62 | |
| parent | c7a3103f41616defdd639ead97ce4ced18ad2206 (diff) | |
| download | luajit-926f688cd0cc177a779ee3bdb2c6a346383dd8e4.tar.gz luajit-926f688cd0cc177a779ee3bdb2c6a346383dd8e4.tar.bz2 luajit-926f688cd0cc177a779ee3bdb2c6a346383dd8e4.zip | |
Canonicalize string conversion of nan, inf, -inf.
| -rw-r--r-- | src/lib_base.c | 3 | ||||
| -rw-r--r-- | src/lib_string.c | 18 | ||||
| -rw-r--r-- | src/lj_str.c | 32 | ||||
| -rw-r--r-- | src/lj_str.h | 1 |
4 files changed, 42 insertions, 12 deletions
diff --git a/src/lib_base.c b/src/lib_base.c index 66b514dc..1f677b50 100644 --- a/src/lib_base.c +++ b/src/lib_base.c | |||
| @@ -413,8 +413,7 @@ LJLIB_CF(print) | |||
| 413 | size = strV(o)->len; | 413 | size = strV(o)->len; |
| 414 | } else if (shortcut && tvisnum(o)) { | 414 | } else if (shortcut && tvisnum(o)) { |
| 415 | char buf[LUAI_MAXNUMBER2STR]; | 415 | char buf[LUAI_MAXNUMBER2STR]; |
| 416 | lua_Number n = numV(o); | 416 | size = lj_str_bufnum(buf, o); |
| 417 | size = (size_t)lua_number2str(buf, n); | ||
| 418 | str = buf; | 417 | str = buf; |
| 419 | } else { | 418 | } else { |
| 420 | copyTV(L, L->top+1, o); | 419 | copyTV(L, L->top+1, o); |
diff --git a/src/lib_string.c b/src/lib_string.c index 1231aeb2..528b3d0e 100644 --- a/src/lib_string.c +++ b/src/lib_string.c | |||
| @@ -734,9 +734,23 @@ LJLIB_CF(string_format) | |||
| 734 | addintlen(form); | 734 | addintlen(form); |
| 735 | sprintf(buff, form, (unsigned LUA_INTFRM_T)lj_lib_checknum(L, arg)); | 735 | sprintf(buff, form, (unsigned LUA_INTFRM_T)lj_lib_checknum(L, arg)); |
| 736 | break; | 736 | break; |
| 737 | case 'e': case 'E': case 'f': case 'g': case 'G': | 737 | case 'e': case 'E': case 'f': case 'g': case 'G': { |
| 738 | sprintf(buff, form, (double)lj_lib_checknum(L, arg)); | 738 | TValue tv; |
| 739 | tv.n = lj_lib_checknum(L, arg); | ||
| 740 | if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) { | ||
| 741 | /* Canonicalize output of non-finite values. */ | ||
| 742 | size_t len = lj_str_bufnum(buff, &tv); | ||
| 743 | if (strfrmt[-1] == 'E' || strfrmt[-1] == 'G') { | ||
| 744 | buff[len-3] = buff[len-3] - 0x20; | ||
| 745 | buff[len-2] = buff[len-2] - 0x20; | ||
| 746 | buff[len-1] = buff[len-1] - 0x20; | ||
| 747 | } | ||
| 748 | luaL_addlstring(&b, buff, len); | ||
| 749 | continue; | ||
| 750 | } | ||
| 751 | sprintf(buff, form, (double)tv.n); | ||
| 739 | break; | 752 | break; |
| 753 | } | ||
| 740 | case 'q': | 754 | case 'q': |
| 741 | addquoted(L, &b, arg); | 755 | addquoted(L, &b, arg); |
| 742 | continue; | 756 | continue; |
diff --git a/src/lj_str.c b/src/lj_str.c index 7b38cecc..4a9477dd 100644 --- a/src/lj_str.c +++ b/src/lj_str.c | |||
| @@ -173,13 +173,27 @@ parsedbl: | |||
| 173 | } | 173 | } |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | /* Print number to buffer. Canonicalizes non-finite values. */ | ||
| 177 | size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) | ||
| 178 | { | ||
| 179 | if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */ | ||
| 180 | lua_Number n = o->n; | ||
| 181 | return (size_t)lua_number2str(s, n); | ||
| 182 | } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) { | ||
| 183 | s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; return 3; | ||
| 184 | } else if ((o->u32.hi & 0x80000000) == 0) { | ||
| 185 | s[0] = 'i'; s[1] = 'n'; s[2] = 'f'; return 3; | ||
| 186 | } else { | ||
| 187 | s[0] = '-'; s[1] = 'i'; s[2] = 'n'; s[3] = 'f'; return 4; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 176 | /* Convert number to string. */ | 191 | /* Convert number to string. */ |
| 177 | GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) | 192 | GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) |
| 178 | { | 193 | { |
| 179 | char s[LUAI_MAXNUMBER2STR]; | 194 | char buf[LUAI_MAXNUMBER2STR]; |
| 180 | lua_Number n = *np; | 195 | size_t len = lj_str_bufnum(buf, (TValue *)np); |
| 181 | size_t len = (size_t)lua_number2str(s, n); | 196 | return lj_str_new(L, buf, len); |
| 182 | return lj_str_new(L, s, len); | ||
| 183 | } | 197 | } |
| 184 | 198 | ||
| 185 | #if LJ_HASJIT | 199 | #if LJ_HASJIT |
| @@ -252,10 +266,12 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp) | |||
| 252 | break; | 266 | break; |
| 253 | } | 267 | } |
| 254 | case 'f': { | 268 | case 'f': { |
| 255 | char buff[LUAI_MAXNUMBER2STR]; | 269 | char buf[LUAI_MAXNUMBER2STR]; |
| 256 | lua_Number n = cast_num(va_arg(argp, LUAI_UACNUMBER)); | 270 | TValue tv; |
| 257 | MSize len = (MSize)lua_number2str(buff, n); | 271 | MSize len; |
| 258 | addstr(L, sb, buff, len); | 272 | tv.n = cast_num(va_arg(argp, LUAI_UACNUMBER)); |
| 273 | len = (MSize)lj_str_bufnum(buf, &tv); | ||
| 274 | addstr(L, sb, buf, len); | ||
| 259 | break; | 275 | break; |
| 260 | } | 276 | } |
| 261 | case 'p': { | 277 | case 'p': { |
diff --git a/src/lj_str.h b/src/lj_str.h index cdb04568..50d1ae5f 100644 --- a/src/lj_str.h +++ b/src/lj_str.h | |||
| @@ -22,6 +22,7 @@ LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s); | |||
| 22 | /* Type conversions. */ | 22 | /* Type conversions. */ |
| 23 | LJ_FUNC int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n); | 23 | LJ_FUNC int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n); |
| 24 | LJ_FUNC int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n); | 24 | LJ_FUNC int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n); |
| 25 | LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o); | ||
| 25 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); | 26 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); |
| 26 | #if LJ_HASJIT | 27 | #if LJ_HASJIT |
| 27 | LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); | 28 | LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); |
