aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-23 12:46:33 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-23 12:46:33 -0300
commit7f5c31cdcac5388b3c48a26112dfb6d2cadb7321 (patch)
tree91012526a941414f1d09e5640d34bee5ccfd240f
parent9e6807c3c9d5036e999f636f936df07b72284442 (diff)
downloadlua-7f5c31cdcac5388b3c48a26112dfb6d2cadb7321.tar.gz
lua-7f5c31cdcac5388b3c48a26112dfb6d2cadb7321.tar.bz2
lua-7f5c31cdcac5388b3c48a26112dfb6d2cadb7321.zip
Fixed bug in 'string.format' with option '%f'
As an example, 'print(string.format("%.99f", 1e70))' may have a lot of garbage after the number. The old test to ensure that 'string.format("%.99f", n)' was not too large, 'fabs(n) < 1e100', assumes that the number will fit in the 99 bytes; but the 99 is not the space for the number, it is the added extra zeros. The option worked for smaller numbers because of the extra space added to MAX_ITEM.
-rw-r--r--lstrlib.c14
-rw-r--r--testes/strings.lua6
2 files changed, 12 insertions, 8 deletions
diff --git a/lstrlib.c b/lstrlib.c
index 563d5ca5..8c9e1a83 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1227,16 +1227,14 @@ static int str_format (lua_State *L) {
1227 nb = lua_number2strx(L, buff, maxitem, form, 1227 nb = lua_number2strx(L, buff, maxitem, form,
1228 luaL_checknumber(L, arg)); 1228 luaL_checknumber(L, arg));
1229 break; 1229 break;
1230 case 'e': case 'E': case 'f': 1230 case 'f':
1231 case 'g': case 'G': { 1231 maxitem = MAX_ITEMF; /* extra space for '%f' */
1232 buff = luaL_prepbuffsize(&b, maxitem);
1233 /* FALLTHROUGH */
1234 case 'e': case 'E': case 'g': case 'G': {
1232 lua_Number n = luaL_checknumber(L, arg); 1235 lua_Number n = luaL_checknumber(L, arg);
1233 if (*(strfrmt - 1) == 'f' && l_mathop(fabs)(n) >= 1e100) {
1234 /* 'n' needs more than 99 digits */
1235 maxitem = MAX_ITEMF; /* extra space for '%f' */
1236 buff = luaL_prepbuffsize(&b, maxitem);
1237 }
1238 addlenmod(form, LUA_NUMBER_FRMLEN); 1236 addlenmod(form, LUA_NUMBER_FRMLEN);
1239 nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n); 1237 nb = snprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
1240 break; 1238 break;
1241 } 1239 }
1242 case 'p': { 1240 case 'p': {
diff --git a/testes/strings.lua b/testes/strings.lua
index 2540fdef..0e7874bf 100644
--- a/testes/strings.lua
+++ b/testes/strings.lua
@@ -255,6 +255,12 @@ do -- longest number that can be formatted
255 local s = string.format('%.99f', -(10^i)) 255 local s = string.format('%.99f', -(10^i))
256 assert(string.len(s) >= i + 101) 256 assert(string.len(s) >= i + 101)
257 assert(tonumber(s) == -(10^i)) 257 assert(tonumber(s) == -(10^i))
258
259 -- limit for floats
260 assert(10^38 < math.huge)
261 local s = string.format('%.99f', -(10^38))
262 assert(string.len(s) >= 38 + 101)
263 assert(tonumber(s) == -(10^38))
258end 264end
259 265
260 266