1
0
Fork 0
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:
liwenxiang1 2024-04-19 15:12:16 +08:00 committed by Xiang Xiao
parent 90afe58ad7
commit 056aa3c816

View file

@ -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