Commit b9f4529f authored by Jonathan Wilkes's avatar Jonathan Wilkes

fix overflow with large precision specifiers

parent cbf0ab07
Pipeline #1403 passed with stage
in 410 minutes and 24 seconds
......@@ -1449,21 +1449,25 @@ static void until_setup(void)
static t_class *makefilename_class;
typedef enum {
NONE = 0,
INT,
FLOAT,
STRING,
POINTER,
} t_printtype;
typedef struct _makefilename
{
t_object x_obj;
t_symbol *x_format;
t_atomtype x_accept;
int x_intconvert;
t_printtype x_accept;
} t_makefilename;
static void makefilename_scanformat(t_makefilename *x)
static const char* makefilename_doscanformat(const char *str, t_printtype *typ)
{
int infmt=0;
char *str;
if (!x->x_format) return;
x->x_accept = A_NULL;
for (str=x->x_format->s_name; *str; str++)
for (; *str; str++)
{
if (!infmt && *str=='%')
{
......@@ -1472,27 +1476,58 @@ static void makefilename_scanformat(t_makefilename *x)
}
if (infmt)
{
if (*str=='%')
{
infmt=0;
continue;
}
if (strchr("-.#0123456789",*str)!=0)
continue;
if (*str=='s')
{
x->x_accept = A_SYMBOL;
x->x_intconvert = 0;
break;
*typ = STRING;
return str;
}
if (strchr("fgGeE",*str)!=0)
{
x->x_accept = A_FLOAT;
x->x_intconvert = 0;
break;
*typ = FLOAT;
return str;
}
if (strchr("xXdiouc",*str)!=0)
{
x->x_accept = A_FLOAT;
x->x_intconvert = 1;
break;
*typ = INT;
return str;
}
if (strchr("p",*str)!=0)
{
*typ = POINTER;
return str;
}
infmt=0;
}
}
*typ = NONE;
return str;
}
static void makefilename_scanformat(t_makefilename *x)
{
const char *str;
t_printtype typ;
if (!x->x_format) return;
str = x->x_format->s_name;
str = makefilename_doscanformat(str, &typ);
x->x_accept = typ;
if (str && (NONE != typ))
{
/* try again, to see if there's another format specifier
(which we forbid) */
str = makefilename_doscanformat(str, &typ);
if (NONE != typ)
{
pd_error(x, "makefilename: invalid format string '%s' "
"(too many format specifiers)", x->x_format->s_name);
x->x_format = 0;
return;
}
}
}
......@@ -1504,40 +1539,113 @@ static void *makefilename_new(t_symbol *s)
s = gensym("file.%d");
outlet_new(&x->x_obj, &s_symbol);
x->x_format = s;
x->x_accept = A_NULL;
x->x_intconvert = 0;
x->x_accept = NONE;
makefilename_scanformat(x);
return (x);
}
static void makefilename_snprintf(t_makefilename *x, char *buf, char *fmt, ...)
{
int length_minus_null_terminator;
va_list ap;
va_start(ap, fmt);
length_minus_null_terminator =
vsnprintf(buf, MAXPDSTRING, fmt, ap);
va_end(ap);
if (length_minus_null_terminator >= MAXPDSTRING)
{
/* Just don't trust snprintf... */
buf[MAXPDSTRING-1] = '\0';
pd_error(x, "makefilename: output truncated to %d characters",
MAXPDSTRING);
}
}
static void makefilename_float(t_makefilename *x, t_floatarg f)
{
char buf[MAXPDSTRING];
if (x->x_accept == A_FLOAT)
if (!x->x_format)
{
if (x->x_intconvert)
sprintf(buf, x->x_format->s_name, (int)f);
else sprintf(buf, x->x_format->s_name, f);
pd_error(x, "makefilename: no format specifier given");
return;
}
else
switch(x->x_accept)
{
case NONE:
makefilename_snprintf(x, buf, "%s", x->x_format->s_name);
break;
case INT: case POINTER:
makefilename_snprintf(x, buf, x->x_format->s_name, (int)f);
break;
case FLOAT:
makefilename_snprintf(x, buf, x->x_format->s_name, f);
break;
case STRING: {
char buf2[MAXPDSTRING];
sprintf(buf2, "%g", f);
sprintf(buf, x->x_format->s_name, buf2);
makefilename_snprintf(x, buf2, "%g", f);
makefilename_snprintf(x, buf, x->x_format->s_name, buf2);
break;
}
default:
makefilename_snprintf(x, buf, "%s", x->x_format->s_name);
}
if (buf[0]!=0)
outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
}
static void makefilename_symbol(t_makefilename *x, t_symbol *s)
{
char buf[MAXPDSTRING];
if (x->x_accept == A_SYMBOL)
sprintf(buf, x->x_format->s_name, s->s_name);
else
sprintf(buf, x->x_format->s_name, 0);
if (!x->x_format)
{
pd_error(x, "makefilename: no format specifier given");
return;
}
switch(x->x_accept)
{
case STRING: case POINTER:
makefilename_snprintf(x, buf, x->x_format->s_name, s->s_name);
break;
case INT:
makefilename_snprintf(x, buf, x->x_format->s_name, 0);
break;
case FLOAT:
makefilename_snprintf(x, buf, x->x_format->s_name, 0.);
break;
case NONE:
makefilename_snprintf(x, buf, "%s", x->x_format->s_name);
break;
default:
makefilename_snprintf(x, buf, "%s", x->x_format->s_name);
}
if (buf[0]!=0)
outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
}
static void makefilename_bang(t_makefilename *x)
{
char buf[MAXPDSTRING];
if(!x->x_format)
{
pd_error(x, "makefilename: no format specifier given");
return;
}
switch(x->x_accept)
{
case INT:
makefilename_snprintf(x, buf, x->x_format->s_name, 0);
break;
case FLOAT:
makefilename_snprintf(x, buf, x->x_format->s_name, 0.);
break;
case NONE:
makefilename_snprintf(x, buf, "%s", x->x_format->s_name);
break;
default:
makefilename_snprintf(x, buf, "%s", x->x_format->s_name);
}
if (buf[0]!=0)
outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
}
static void makefilename_set(t_makefilename *x, t_symbol *s)
......@@ -1553,6 +1661,7 @@ static void makefilename_setup(void)
sizeof(t_makefilename), 0, A_DEFSYM, 0);
class_addfloat(makefilename_class, makefilename_float);
class_addsymbol(makefilename_class, makefilename_symbol);
class_addbang(makefilename_class, makefilename_bang);
class_addmethod(makefilename_class, (t_method)makefilename_set,
gensym("set"), A_SYMBOL, 0);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment