Fix the implementation of vasprintf to work with ORCA/C's varargs implementation. Also, shrink the stack-allocated buffer in it.

This code could theoretically break if the ORCA/C varargs implementation changed, but it should be OK in practice.

Also removed some unused code in libbb/xfuncs.printf.c that includes potentially problematic varargs use (defining varargs functions but not necessarily calling va_start/va_end in them).
This commit is contained in:
Stephen Heumann 2014-11-03 16:08:43 -06:00
parent bdafda3f97
commit 32e9dccc33
2 changed files with 19 additions and 73 deletions

View File

@ -36,27 +36,42 @@ int FAST_FUNC usleep(unsigned usec)
#endif
#ifndef HAVE_VASPRINTF
#ifndef __ORCAC__
# define VASPRINTF_BUF_SIZE 128
#else
# define VASPRINTF_BUF_SIZE 8
#endif
int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p)
{
int r;
va_list p2;
char buf[128];
char buf[VASPRINTF_BUF_SIZE];
#ifndef __ORCAC__
va_copy(p2, p);
r = vsnprintf(buf, 128, format, p);
va_end(p);
#else
// ORCA/C doesn't have va_copy, so copy it manually instead.
// Don't call va_end on the copy, because that would mess up the stack.
memcpy(p2, p, sizeof(va_list));
#endif
r = vsnprintf(buf, VASPRINTF_BUF_SIZE, format, p);
/* Note: can't use xstrdup/xmalloc, they call vasprintf (us) on failure! */
if (r < 128) {
if (r < VASPRINTF_BUF_SIZE) {
#ifndef __ORCAC__
va_end(p2);
#endif
*string_ptr = strdup(buf);
return (*string_ptr ? r : -1);
}
*string_ptr = malloc(r+1);
r = (*string_ptr ? vsnprintf(*string_ptr, r+1, format, p2) : -1);
#ifndef __ORCAC__
va_end(p2);
#endif
return r;
}

View File

@ -477,75 +477,6 @@ void FAST_FUNC selinux_or_die(void)
#endif
}
int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...)
{
int ret;
va_list p;
ret = ioctl(fd, request, argp);
if (ret < 0) {
va_start(p, fmt);
bb_verror_msg(fmt, p, strerror(errno));
/* xfunc_die can actually longjmp, so be nice */
va_end(p);
xfunc_die();
}
return ret;
}
int FAST_FUNC ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...)
{
va_list p;
int ret = ioctl(fd, request, argp);
if (ret < 0) {
va_start(p, fmt);
bb_verror_msg(fmt, p, strerror(errno));
va_end(p);
}
return ret;
}
#if ENABLE_IOCTL_HEX2STR_ERROR
int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp, const char *ioctl_name)
{
int ret;
ret = ioctl(fd, request, argp);
if (ret < 0)
bb_simple_perror_msg(ioctl_name);
return ret;
}
int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp, const char *ioctl_name)
{
int ret;
ret = ioctl(fd, request, argp);
if (ret < 0)
bb_simple_perror_msg_and_die(ioctl_name);
return ret;
}
#else
int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp)
{
int ret;
ret = ioctl(fd, request, argp);
if (ret < 0)
bb_perror_msg("ioctl %#x failed", request);
return ret;
}
int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp)
{
int ret;
ret = ioctl(fd, request, argp);
if (ret < 0)
bb_perror_msg_and_die("ioctl %#x failed", request);
return ret;
}
#endif
#if BB_MMU
pid_t FAST_FUNC xfork(void)
{