Skip to content

Commit

Permalink
libs/libc: Optimize the stack space of lib_vsprintf by splitting argl…
Browse files Browse the repository at this point in the history
…ist into type and value

Dynamically apply for memory based on numargs

Signed-off-by: liwenxiang1 <[email protected]>

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 <[email protected]>
  • Loading branch information
xianglyc authored and xiaoxiang781216 committed Oct 12, 2024
1 parent 90afe58 commit 056aa3c
Showing 1 changed file with 44 additions and 41 deletions.
85 changes: 44 additions & 41 deletions libs/libc/stdio/lib_libvsprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

#include <assert.h>
#include <string.h>
#include <sys/param.h>

#include "lib_dtoa_engine.h"
#include "lib_ultoa_invert.h"
Expand Down Expand Up @@ -117,21 +118,22 @@
* Private Types
****************************************************************************/

struct arg_s
union arg_u
{
unsigned char type;
union
{
unsigned int u;
unsigned long ul;
unsigned int u;
unsigned long ul;
#ifdef CONFIG_HAVE_LONG_LONG
unsigned long long ull;
unsigned long long ull;
#endif
#ifdef CONFIG_HAVE_DOUBLE
double d;
double d;
FAR char *cp;
};
struct arg_s
{
#ifdef CONFIG_LIBC_NUMBERED_ARGS
unsigned char type[NL_ARGMAX];
#endif
FAR char *cp;
} value;
FAR union arg_u *value;
};

/****************************************************************************
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
}
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -602,7 +604,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#ifdef CONFIG_LIBC_NUMBERED_ARGS
if ((flags & FL_ARGNUMBER) != 0)
{
value = arglist[argnumber - 1].value.d;
value = arglist->value[argnumber - 1].d;
}
else
{
Expand Down Expand Up @@ -896,7 +898,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#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
{
Expand All @@ -914,7 +916,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#ifdef CONFIG_LIBC_NUMBERED_ARGS
if ((flags & FL_ARGNUMBER) != 0)
{
pnt = arglist[argnumber - 1].value.cp;
pnt = arglist->value[argnumber - 1].cp;
}
else
{
Expand Down Expand Up @@ -959,7 +961,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#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
{
Expand All @@ -976,7 +978,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#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
{
Expand All @@ -991,7 +993,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#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
{
Expand Down Expand Up @@ -1045,7 +1047,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#ifdef CONFIG_LIBC_NUMBERED_ARGS
if ((flags & FL_ARGNUMBER) != 0)
{
x = arglist[argnumber - 1].value.ull;
x = arglist->value[argnumber - 1].ull;
}
else
{
Expand All @@ -1062,7 +1064,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#ifdef CONFIG_LIBC_NUMBERED_ARGS
if ((flags & FL_ARGNUMBER) != 0)
{
x = arglist[argnumber - 1].value.ul;
x = arglist->value[argnumber - 1].ul;
}
else
{
Expand All @@ -1077,7 +1079,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream,
#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
{
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 056aa3c

Please sign in to comment.