1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-05 19:35:52 +03:00

libio: asprintf should write NULL upon failure

This was suggested most recently by Solar Designer, noting
that code replacing vsprintf with vasprintf in a security fix
was subtly wrong:

  Re: GStreamer Security Advisory 2024-0003: Orc compiler
  stack-based buffer overflow
  <https://www.openwall.com/lists/oss-security/2024/07/26/2>

Previous libc-alpha discussions:

  I: [PATCH] asprintf error handling fix
  <https://inbox.sourceware.org/libc-alpha/20011205185828.GA8376@ldv.office.alt-linux.org/>

  asprintf() issue
  <https://inbox.sourceware.org/libc-alpha/CANSoFxt-cdc-+C4u-rTENMtY4X9RpRSuv+axDswSPxbDgag8_Q@mail.gmail.com/>

I don't think we need a compatibility symbol for this.  As the
GStreamer example shows, this change is much more likely to fix bugs
than cause compatibility issues.

Suggested-by: Dmitry V. Levin <ldv@altlinux.org>
Suggested-by: Archie Cobbs <archie.cobbs@gmail.com>
Suggested-by: Solar Designer <solar@openwall.com>
Reviewed-by: Sam James <sam@gentoo.org>
This commit is contained in:
Florian Weimer
2024-12-27 09:17:41 +01:00
parent 7c22dcda27
commit cb4692ce1e
4 changed files with 68 additions and 10 deletions

View File

@@ -92,7 +92,7 @@ __printf_buffer_flush_asprintf (struct __printf_buffer_asprintf *buf)
int
__vasprintf_internal (char **result_ptr, const char *format, va_list args,
__vasprintf_internal (char **result, const char *format, va_list args,
unsigned int mode_flags)
{
struct __printf_buffer_asprintf buf;
@@ -105,23 +105,23 @@ __vasprintf_internal (char **result_ptr, const char *format, va_list args,
{
if (buf.base.write_base != buf.direct)
free (buf.base.write_base);
*result = NULL;
return done;
}
/* Transfer to the final buffer. */
char *result;
size_t size = buf.base.write_ptr - buf.base.write_base;
if (buf.base.write_base == buf.direct)
{
result = malloc (size + 1);
if (result == NULL)
*result = malloc (size + 1);
if (*result == NULL)
return -1;
memcpy (result, buf.direct, size);
memcpy (*result, buf.direct, size);
}
else
{
result = realloc (buf.base.write_base, size + 1);
if (result == NULL)
*result = realloc (buf.base.write_base, size + 1);
if (*result == NULL)
{
free (buf.base.write_base);
return -1;
@@ -129,8 +129,7 @@ __vasprintf_internal (char **result_ptr, const char *format, va_list args,
}
/* Add NUL termination. */
result[size] = '\0';
*result_ptr = result;
(*result)[size] = '\0';
return done;
}