mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-22 17:08:53 +02:00
glib/gnulib/printf.c: Sync with gnulib
Sync _g_gnulib_vsprintf() with lib/vszprintf.c and _g_gnulib_vsnprintf() with lib/vsnzprintf.c from gnulib, plus adjust the final guards to handle differing return signatures. Highlights: - Avoid a memory allocation if the result fits into the provided buffer. https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commit;h=f5200a50fa42fdaed40ecc67b27f41be328a6a01 - Don't assume vasnprintf returns EOVERFLOW if the size exceeds INT_MAX; do the check ourselves. https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commit;h=7e421d1cd6a8752aa527895c759a72a47203959a
This commit is contained in:
@@ -23,12 +23,18 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h> /* for INT_MAX */
|
||||
#include <stdint.h> /* for uintptr_t, SIZE_MAX */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "printf.h"
|
||||
|
||||
#include "g-gnulib.h"
|
||||
#include "vasnprintf.h"
|
||||
#include "printf.h"
|
||||
|
||||
int _g_gnulib_printf (char const *format, ...)
|
||||
{
|
||||
@@ -98,39 +104,71 @@ int _g_gnulib_vfprintf (FILE *file, char const *format, va_list args)
|
||||
return rlength;
|
||||
}
|
||||
|
||||
int _g_gnulib_vsprintf (char *string, char const *format, va_list args)
|
||||
int _g_gnulib_vsprintf (char *str, char const *format, va_list args)
|
||||
{
|
||||
char *result;
|
||||
size_t length;
|
||||
char *output;
|
||||
size_t len;
|
||||
size_t lenbuf;
|
||||
|
||||
result = vasnprintf (NULL, &length, format, args);
|
||||
if (result == NULL)
|
||||
/* Set lenbuf = min (SIZE_MAX, - (uintptr_t) str - 1). */
|
||||
lenbuf = SIZE_MAX;
|
||||
if (lenbuf >= ~ (uintptr_t) str)
|
||||
lenbuf = ~ (uintptr_t) str;
|
||||
|
||||
output = vasnprintf (str, &lenbuf, format, args);
|
||||
len = lenbuf;
|
||||
|
||||
if (!output)
|
||||
return -1;
|
||||
|
||||
memcpy (string, result, length + 1);
|
||||
free (result);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int _g_gnulib_vsnprintf (char *string, size_t n, char const *format, va_list args)
|
||||
{
|
||||
char *result;
|
||||
size_t length;
|
||||
|
||||
result = vasnprintf (NULL, &length, format, args);
|
||||
if (result == NULL)
|
||||
return -1;
|
||||
|
||||
if (n > 0)
|
||||
if (output != str)
|
||||
{
|
||||
memcpy (string, result, MIN(length + 1, n));
|
||||
string[n - 1] = 0;
|
||||
/* len is near SIZE_MAX. */
|
||||
free (output);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (result);
|
||||
|
||||
return length;
|
||||
if (len > INT_MAX)
|
||||
{
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int _g_gnulib_vsnprintf (char *str, size_t size, char const *format, va_list args)
|
||||
{
|
||||
char *output;
|
||||
size_t len;
|
||||
size_t lenbuf = size;
|
||||
|
||||
output = vasnprintf (str, &lenbuf, format, args);
|
||||
len = lenbuf;
|
||||
|
||||
if (!output)
|
||||
return -1;
|
||||
|
||||
if (output != str)
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
size_t pruned_len = (len < size ? len : size - 1);
|
||||
memcpy (str, output, pruned_len);
|
||||
str[pruned_len] = '\0';
|
||||
}
|
||||
|
||||
free (output);
|
||||
}
|
||||
|
||||
if (len > INT_MAX)
|
||||
{
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int _g_gnulib_vasprintf (char **result, char const *format, va_list args)
|
||||
|
Reference in New Issue
Block a user