format "%s" may break limit of "sprintf" on some machines.

This commit is contained in:
Roberto Ierusalimschy 1999-02-04 17:29:51 -02:00
parent 76179a1014
commit 1dcf1c9cbd
2 changed files with 17 additions and 9 deletions

3
bugs
View File

@ -67,3 +67,6 @@ Wed Feb 3 14:40:21 EDT 1999
>> getlocal cannot return the local itself, since lua_isstring and >> getlocal cannot return the local itself, since lua_isstring and
lua_isnumber can modify it. lua_isnumber can modify it.
** lstrlib.c
Thu Feb 4 17:08:50 EDT 1999
>> format "%s" may break limit of "sprintf" on some machines.

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstrlib.c,v 1.22 1998/12/28 13:44:54 roberto Exp $ ** $Id: lstrlib.c,v 1.24 1999/02/04 19:10:30 roberto Exp roberto $
** Standard library for strings and pattern-matching ** Standard library for strings and pattern-matching
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -462,8 +462,6 @@ static void luaI_addquoted (int arg) {
static void str_format (void) { static void str_format (void) {
int arg = 1; int arg = 1;
char *strfrmt = luaL_check_string(arg); char *strfrmt = luaL_check_string(arg);
struct Capture cap;
cap.src_end = strfrmt+strlen(strfrmt)+1;
luaL_resetbuffer(); luaL_resetbuffer();
while (*strfrmt) { while (*strfrmt) {
if (*strfrmt != '%') if (*strfrmt != '%')
@ -471,33 +469,40 @@ static void str_format (void) {
else if (*++strfrmt == '%') else if (*++strfrmt == '%')
luaL_addchar(*strfrmt++); /* %% */ luaL_addchar(*strfrmt++); /* %% */
else { /* format item */ else { /* format item */
struct Capture cap;
char form[MAX_FORMAT]; /* store the format ('%...') */ char form[MAX_FORMAT]; /* store the format ('%...') */
char *buff; char *buff;
char *initf = strfrmt; char *initf = strfrmt;
form[0] = '%'; form[0] = '%';
cap.level = 0;
if (isdigit((unsigned char)initf[0]) && initf[1] == '$') { if (isdigit((unsigned char)initf[0]) && initf[1] == '$') {
arg = initf[0] - '0'; arg = initf[0] - '0';
initf += 2; /* skip the 'n$' */ initf += 2; /* skip the 'n$' */
} }
arg++; arg++;
cap.src_end = strfrmt+strlen(strfrmt)+1;
cap.level = 0;
strfrmt = match(initf, "[-+ #0]*(%d*)%.?(%d*)", &cap); strfrmt = match(initf, "[-+ #0]*(%d*)%.?(%d*)", &cap);
if (cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */ if (cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */
strfrmt-initf > MAX_FORMAT-2) strfrmt-initf > MAX_FORMAT-2)
lua_error("invalid format (width or precision too long)"); lua_error("invalid format (width or precision too long)");
strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */ strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */
form[strfrmt-initf+2] = 0; form[strfrmt-initf+2] = 0;
/* to store the formatted value buff = luaL_openspace(450); /* 450 > size of format('%99.99f', -1e308) */
(450 > size of format('%99.99f', -1e308) */
buff = luaL_openspace(450);
switch (*strfrmt++) { switch (*strfrmt++) {
case 'q': case 'q':
luaI_addquoted(arg); luaI_addquoted(arg);
continue; continue;
case 's': { case 's': {
char *s = luaL_check_string(arg); char *s = luaL_check_string(arg);
buff = luaL_openspace(strlen(s)); int l = strlen(s);
sprintf(buff, form, s); buff = luaL_openspace(l+1);
if (cap.capture[1].len == 0 && l >= 100) {
/* no precision and string is too big to be formated;
keep original string */
strcpy(buff, s);
}
else
sprintf(buff, form, s);
break; break;
} }
case 'c': case 'd': case 'i': case 'c': case 'd': case 'i':