forked from nuttx/nuttx-update
libs/libc: Optimize the stack space of lib_vsprintf by splitting arglist into type and value
Dynamically apply for memory based on numargs Signed-off-by: liwenxiang1 <liwenxiang1@xiaomi.com> libs/libc: Resolve the issue of undefined behavior when UBSAN is enabled on SIM If numargs equals 0, it is set to 1 by default Signed-off-by: liwenxiang1 <liwenxiang1@xiaomi.com>
This commit is contained in:
parent
90afe58ad7
commit
056aa3c816
1 changed files with 45 additions and 42 deletions
|
@ -48,6 +48,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "lib_dtoa_engine.h"
|
||||
#include "lib_ultoa_invert.h"
|
||||
|
@ -117,21 +118,22 @@
|
|||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
union arg_u
|
||||
{
|
||||
unsigned int u;
|
||||
unsigned long ul;
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
unsigned long long ull;
|
||||
#endif
|
||||
double d;
|
||||
FAR char *cp;
|
||||
};
|
||||
struct arg_s
|
||||
{
|
||||
unsigned char type;
|
||||
union
|
||||
{
|
||||
unsigned int u;
|
||||
unsigned long ul;
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
unsigned long long ull;
|
||||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
unsigned char type[NL_ARGMAX];
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_DOUBLE
|
||||
double d;
|
||||
#endif
|
||||
FAR char *cp;
|
||||
} value;
|
||||
FAR union arg_u *value;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -291,7 +293,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
|
|||
{
|
||||
if (stream == NULL)
|
||||
{
|
||||
arglist[index - 1].type = TYPE_INT;
|
||||
arglist->type[index - 1] = TYPE_INT;
|
||||
if (index > total_len)
|
||||
{
|
||||
total_len = index;
|
||||
|
@ -301,11 +303,11 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
|
|||
{
|
||||
if ((flags & FL_PREC) == 0)
|
||||
{
|
||||
width = (int)arglist[index - 1].value.u;
|
||||
width = (int)arglist->value[index - 1].u;
|
||||
}
|
||||
else
|
||||
{
|
||||
prec = (int)arglist[index - 1].value.u;
|
||||
prec = (int)arglist->value[index - 1].u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -503,30 +505,30 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
|
|||
if ((c >= 'E' && c <= 'G')
|
||||
|| (c >= 'e' && c <= 'g'))
|
||||
{
|
||||
arglist[argnumber - 1].type = TYPE_DOUBLE;
|
||||
arglist->type[argnumber - 1] = TYPE_DOUBLE;
|
||||
}
|
||||
else if (c == 'i' || c == 'd' || c == 'u' || c == 'p')
|
||||
{
|
||||
if ((flags & FL_LONG) == 0)
|
||||
{
|
||||
arglist[argnumber - 1].type = TYPE_INT;
|
||||
arglist->type[argnumber - 1] = TYPE_INT;
|
||||
}
|
||||
else if ((flags & FL_REPD_TYPE) == 0)
|
||||
{
|
||||
arglist[argnumber - 1].type = TYPE_LONG;
|
||||
arglist->type[argnumber - 1] = TYPE_LONG;
|
||||
}
|
||||
else
|
||||
{
|
||||
arglist[argnumber - 1].type = TYPE_LONG_LONG;
|
||||
arglist->type[argnumber - 1] = TYPE_LONG_LONG;
|
||||
}
|
||||
}
|
||||
else if (c == 'c')
|
||||
{
|
||||
arglist[argnumber - 1].type = TYPE_INT;
|
||||
arglist->type[argnumber - 1] = TYPE_INT;
|
||||
}
|
||||
else if (c == 's')
|
||||
{
|
||||
arglist[argnumber - 1].type = TYPE_CHAR_POINTER;
|
||||
arglist->type[argnumber - 1] = TYPE_CHAR_POINTER;
|
||||
}
|
||||
|
||||
if (argnumber > total_len)
|
||||
|
@ -602,7 +604,7 @@ flt_oper:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
value = arglist[argnumber - 1].value.d;
|
||||
value = arglist->value[argnumber - 1].d;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -896,7 +898,7 @@ flt_oper:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
buf[0] = (int)arglist[argnumber - 1].value.u;
|
||||
buf[0] = (int)arglist->value[argnumber - 1].u;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -914,7 +916,7 @@ flt_oper:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
pnt = arglist[argnumber - 1].value.cp;
|
||||
pnt = arglist->value[argnumber - 1].cp;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -959,7 +961,7 @@ str_lpad:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
x = (long long)arglist[argnumber - 1].value.ull;
|
||||
x = (long long)arglist->value[argnumber - 1].ull;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -976,7 +978,7 @@ str_lpad:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
x = (long)arglist[argnumber - 1].value.ul;
|
||||
x = (long)arglist->value[argnumber - 1].ul;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -991,7 +993,7 @@ str_lpad:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
x = (int)arglist[argnumber - 1].value.u;
|
||||
x = (int)arglist->value[argnumber - 1].u;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1045,7 +1047,7 @@ str_lpad:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
x = arglist[argnumber - 1].value.ull;
|
||||
x = arglist->value[argnumber - 1].ull;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1062,7 +1064,7 @@ str_lpad:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
x = arglist[argnumber - 1].value.ul;
|
||||
x = arglist->value[argnumber - 1].ul;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1077,7 +1079,7 @@ str_lpad:
|
|||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
if ((flags & FL_ARGNUMBER) != 0)
|
||||
{
|
||||
x = (unsigned int)arglist[argnumber - 1].value.u;
|
||||
x = (unsigned int)arglist->value[argnumber - 1].u;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1325,45 +1327,46 @@ int lib_vsprintf(FAR struct lib_outstream_s *stream,
|
|||
FAR const IPTR char *fmt, va_list ap)
|
||||
{
|
||||
#ifdef CONFIG_LIBC_NUMBERED_ARGS
|
||||
struct arg_s arglist[NL_ARGMAX];
|
||||
int numargs;
|
||||
int i;
|
||||
|
||||
/* We do 2 passes of parsing and fill the arglist between the passes. */
|
||||
|
||||
numargs = vsprintf_internal(NULL, arglist, NL_ARGMAX, fmt, ap);
|
||||
struct arg_s arglist;
|
||||
int numargs = vsprintf_internal(NULL, &arglist, NL_ARGMAX, fmt, ap);
|
||||
union arg_u argvalue[MAX(numargs, 1)];
|
||||
int i;
|
||||
|
||||
arglist.value = argvalue;
|
||||
|
||||
for (i = 0; i < numargs; i++)
|
||||
{
|
||||
switch (arglist[i].type)
|
||||
switch (arglist.type[i])
|
||||
{
|
||||
case TYPE_LONG_LONG:
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
arglist[i].value.ull = va_arg(ap, unsigned long long);
|
||||
arglist.value[i].ull = va_arg(ap, unsigned long long);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TYPE_LONG:
|
||||
arglist[i].value.ul = va_arg(ap, unsigned long);
|
||||
arglist.value[i].ul = va_arg(ap, unsigned long);
|
||||
break;
|
||||
|
||||
case TYPE_INT:
|
||||
arglist[i].value.u = va_arg(ap, unsigned int);
|
||||
arglist.value[i].u = va_arg(ap, unsigned int);
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_HAVE_DOUBLE
|
||||
case TYPE_DOUBLE:
|
||||
arglist[i].value.d = va_arg(ap, double);
|
||||
arglist.value[i].d = va_arg(ap, double);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TYPE_CHAR_POINTER:
|
||||
arglist[i].value.cp = va_arg(ap, FAR char *);
|
||||
arglist.value[i].cp = va_arg(ap, FAR char *);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vsprintf_internal(stream, arglist, numargs, fmt, ap);
|
||||
return vsprintf_internal(stream, &arglist, numargs, fmt, ap);
|
||||
#else
|
||||
return vsprintf_internal(stream, NULL, 0, fmt, ap);
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue