aboutsummaryrefslogtreecommitdiff
path: root/lstrlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'lstrlib.c')
-rw-r--r--lstrlib.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/lstrlib.c b/lstrlib.c
index 53ed80a3..563d5ca5 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1038,13 +1038,23 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
1038 1038
1039 1039
1040/* 1040/*
1041** Maximum size of each formatted item. This maximum size is produced 1041** Maximum size for items formatted with '%f'. This size is produced
1042** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', 1042** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
1043** and '\0') + number of decimal digits to represent maxfloat (which 1043** and '\0') + number of decimal digits to represent maxfloat (which
1044** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra 1044** is maximum exponent + 1). (99+3+1, adding some extra, 110)
1045** expenses", such as locale-dependent stuff)
1046*/ 1045*/
1047#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) 1046#define MAX_ITEMF (110 + l_mathlim(MAX_10_EXP))
1047
1048
1049/*
1050** All formats except '%f' do not need that large limit. The other
1051** float formats use exponents, so that they fit in the 99 limit for
1052** significant digits; 's' for large strings and 'q' add items directly
1053** to the buffer; all integer formats also fit in the 99 limit. The
1054** worst case are floats: they may need 99 significant digits, plus
1055** '0x', '-', '.', 'e+XXXX', and '\0'. Adding some extra, 120.
1056*/
1057#define MAX_ITEM 120
1048 1058
1049 1059
1050/* valid flags in a format specification */ 1060/* valid flags in a format specification */
@@ -1194,38 +1204,44 @@ static int str_format (lua_State *L) {
1194 luaL_addchar(&b, *strfrmt++); /* %% */ 1204 luaL_addchar(&b, *strfrmt++); /* %% */
1195 else { /* format item */ 1205 else { /* format item */
1196 char form[MAX_FORMAT]; /* to store the format ('%...') */ 1206 char form[MAX_FORMAT]; /* to store the format ('%...') */
1197 char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ 1207 int maxitem = MAX_ITEM;
1208 char *buff = luaL_prepbuffsize(&b, maxitem); /* to put formatted item */
1198 int nb = 0; /* number of bytes in added item */ 1209 int nb = 0; /* number of bytes in added item */
1199 if (++arg > top) 1210 if (++arg > top)
1200 return luaL_argerror(L, arg, "no value"); 1211 return luaL_argerror(L, arg, "no value");
1201 strfrmt = scanformat(L, strfrmt, form); 1212 strfrmt = scanformat(L, strfrmt, form);
1202 switch (*strfrmt++) { 1213 switch (*strfrmt++) {
1203 case 'c': { 1214 case 'c': {
1204 nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); 1215 nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
1205 break; 1216 break;
1206 } 1217 }
1207 case 'd': case 'i': 1218 case 'd': case 'i':
1208 case 'o': case 'u': case 'x': case 'X': { 1219 case 'o': case 'u': case 'x': case 'X': {
1209 lua_Integer n = luaL_checkinteger(L, arg); 1220 lua_Integer n = luaL_checkinteger(L, arg);
1210 addlenmod(form, LUA_INTEGER_FRMLEN); 1221 addlenmod(form, LUA_INTEGER_FRMLEN);
1211 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); 1222 nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
1212 break; 1223 break;
1213 } 1224 }
1214 case 'a': case 'A': 1225 case 'a': case 'A':
1215 addlenmod(form, LUA_NUMBER_FRMLEN); 1226 addlenmod(form, LUA_NUMBER_FRMLEN);
1216 nb = lua_number2strx(L, buff, MAX_ITEM, form, 1227 nb = lua_number2strx(L, buff, maxitem, form,
1217 luaL_checknumber(L, arg)); 1228 luaL_checknumber(L, arg));
1218 break; 1229 break;
1219 case 'e': case 'E': case 'f': 1230 case 'e': case 'E': case 'f':
1220 case 'g': case 'G': { 1231 case 'g': case 'G': {
1221 lua_Number n = luaL_checknumber(L, arg); 1232 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 }
1222 addlenmod(form, LUA_NUMBER_FRMLEN); 1238 addlenmod(form, LUA_NUMBER_FRMLEN);
1223 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); 1239 nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
1224 break; 1240 break;
1225 } 1241 }
1226 case 'p': { 1242 case 'p': {
1227 const void *p = lua_topointer(L, arg); 1243 const void *p = lua_topointer(L, arg);
1228 nb = l_sprintf(buff, MAX_ITEM, form, p); 1244 nb = l_sprintf(buff, maxitem, form, p);
1229 break; 1245 break;
1230 } 1246 }
1231 case 'q': { 1247 case 'q': {
@@ -1246,7 +1262,7 @@ static int str_format (lua_State *L) {
1246 luaL_addvalue(&b); /* keep entire string */ 1262 luaL_addvalue(&b); /* keep entire string */
1247 } 1263 }
1248 else { /* format the string into 'buff' */ 1264 else { /* format the string into 'buff' */
1249 nb = l_sprintf(buff, MAX_ITEM, form, s); 1265 nb = l_sprintf(buff, maxitem, form, s);
1250 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ 1266 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
1251 } 1267 }
1252 } 1268 }
@@ -1256,7 +1272,7 @@ static int str_format (lua_State *L) {
1256 return luaL_error(L, "invalid conversion '%s' to 'format'", form); 1272 return luaL_error(L, "invalid conversion '%s' to 'format'", form);
1257 } 1273 }
1258 } 1274 }
1259 lua_assert(nb < MAX_ITEM); 1275 lua_assert(nb < maxitem);
1260 luaL_addsize(&b, nb); 1276 luaL_addsize(&b, nb);
1261 } 1277 }
1262 } 1278 }