Explorar o código

Canonicalize string conversion of nan, inf, -inf.

Mike Pall %!s(int64=15) %!d(string=hai) anos
pai
achega
926f688cd0
Modificáronse 4 ficheiros con 42 adicións e 12 borrados
  1. 1 2
      src/lib_base.c
  2. 16 2
      src/lib_string.c
  3. 24 8
      src/lj_str.c
  4. 1 0
      src/lj_str.h

+ 1 - 2
src/lib_base.c

@@ -413,8 +413,7 @@ LJLIB_CF(print)
       size = strV(o)->len;
     } else if (shortcut && tvisnum(o)) {
       char buf[LUAI_MAXNUMBER2STR];
-      lua_Number n = numV(o);
-      size = (size_t)lua_number2str(buf, n);
+      size = lj_str_bufnum(buf, o);
       str = buf;
     } else {
       copyTV(L, L->top+1, o);

+ 16 - 2
src/lib_string.c

@@ -734,9 +734,23 @@ LJLIB_CF(string_format)
 	addintlen(form);
 	sprintf(buff, form, (unsigned LUA_INTFRM_T)lj_lib_checknum(L, arg));
 	break;
-      case 'e':  case 'E': case 'f': case 'g': case 'G':
-	sprintf(buff, form, (double)lj_lib_checknum(L, arg));
+      case 'e':  case 'E': case 'f': case 'g': case 'G': {
+	TValue tv;
+	tv.n = lj_lib_checknum(L, arg);
+	if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) {
+	  /* Canonicalize output of non-finite values. */
+	  size_t len = lj_str_bufnum(buff, &tv);
+	  if (strfrmt[-1] == 'E' || strfrmt[-1] == 'G') {
+	    buff[len-3] = buff[len-3] - 0x20;
+	    buff[len-2] = buff[len-2] - 0x20;
+	    buff[len-1] = buff[len-1] - 0x20;
+	  }
+	  luaL_addlstring(&b, buff, len);
+	  continue;
+	}
+	sprintf(buff, form, (double)tv.n);
 	break;
+	}
       case 'q':
 	addquoted(L, &b, arg);
 	continue;

+ 24 - 8
src/lj_str.c

@@ -173,13 +173,27 @@ parsedbl:
   }
 }
 
+/* Print number to buffer. Canonicalizes non-finite values. */
+size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o)
+{
+  if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) {  /* Finite? */
+    lua_Number n = o->n;
+    return (size_t)lua_number2str(s, n);
+  } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) {
+    s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; return 3;
+  } else if ((o->u32.hi & 0x80000000) == 0) {
+    s[0] = 'i'; s[1] = 'n'; s[2] = 'f'; return 3;
+  } else {
+    s[0] = '-'; s[1] = 'i'; s[2] = 'n'; s[3] = 'f'; return 4;
+  }
+}
+
 /* Convert number to string. */
 GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np)
 {
-  char s[LUAI_MAXNUMBER2STR];
-  lua_Number n = *np;
-  size_t len = (size_t)lua_number2str(s, n);
-  return lj_str_new(L, s, len);
+  char buf[LUAI_MAXNUMBER2STR];
+  size_t len = lj_str_bufnum(buf, (TValue *)np);
+  return lj_str_new(L, buf, len);
 }
 
 #if LJ_HASJIT
@@ -252,10 +266,12 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
       break;
       }
     case 'f': {
-      char buff[LUAI_MAXNUMBER2STR];
-      lua_Number n = cast_num(va_arg(argp, LUAI_UACNUMBER));
-      MSize len = (MSize)lua_number2str(buff, n);
-      addstr(L, sb, buff, len);
+      char buf[LUAI_MAXNUMBER2STR];
+      TValue tv;
+      MSize len;
+      tv.n = cast_num(va_arg(argp, LUAI_UACNUMBER));
+      len = (MSize)lj_str_bufnum(buf, &tv);
+      addstr(L, sb, buf, len);
       break;
       }
     case 'p': {

+ 1 - 0
src/lj_str.h

@@ -22,6 +22,7 @@ LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s);
 /* Type conversions. */
 LJ_FUNC int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n);
 LJ_FUNC int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n);
+LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o);
 LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np);
 #if LJ_HASJIT
 LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k);