summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Schleifer <js@nil.im>2020-05-16 18:46:42 +0200
committerJonathan Schleifer <js@nil.im>2020-05-16 18:46:42 +0200
commit0f18bfc5b46d07b4cc80d9669eb03a19e6c12eb2 (patch)
tree6e5e50c5bd634db9a620e96cf4ad12f33ade0960
parent745efd25ded8af30c49f96819b0d109d928b8238 (diff)
Do not require snprintf to return expected length
-rw-r--r--configure.ac32
-rw-r--r--src/of_asprintf.m39
2 files changed, 40 insertions, 31 deletions
diff --git a/configure.ac b/configure.ac
index 5bb45a3e..1eca62bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,7 +40,6 @@ case "$host" in
enable_threads="no"
enable_sockets="no"
enable_files="no"
- ac_cv_snprintf_useful_ret="yes"
;;
m68k-*-amigaos*)
AS_IF([test x"$OBJCFLAGS" = x""], [
@@ -54,7 +53,6 @@ case "$host" in
enable_files="yes" # Required for reading ENV:
enable_shared="no"
supports_amiga_lib="yes"
- ac_cv_snprintf_useful_ret="yes"
AS_IF([test x"$enable_amiga_lib" != x"no"], [
AC_SUBST(OBJFWRT_AMIGA_LIB, objfwrt68k.library)
@@ -830,10 +828,14 @@ AC_CHECK_LIB(complex, creal, TESTS_LIBS="$TESTS_LIBS -lcomplex")
AC_CHECK_FUNC(asprintf, [
case "$host" in
+ *-*-mingw*)
+ dnl asprintf from MinGW is broken on older Windows
+ dnl versions
+ have_asprintf="no"
+ ;;
*-psp-*)
- dnl asprintf is broken on the PSP, but snprintf works.
+ dnl asprintf is broken on the PSP
have_asprintf="no"
- ac_cv_snprintf_useful_ret="yes"
;;
*)
have_asprintf="yes"
@@ -843,29 +845,7 @@ AC_CHECK_FUNC(asprintf, [
esac
], [
have_asprintf="no"
-
- AC_MSG_CHECKING(whether snprintf returns something useful)
- AC_CACHE_VAL(ac_cv_snprintf_useful_ret, [
- AC_TRY_RUN([
- #include <stdio.h>
-
- int
- main()
- {
- return (snprintf(NULL, 0, "asd") == 3 ? 0 : 1);
- }
- ], [
- ac_cv_snprintf_useful_ret="yes"
- ], [
- ac_cv_snprintf_useful_ret="no"
- ], [
- ac_cv_snprintf_useful_ret="no"
- ])
- ])
- AC_MSG_RESULT($ac_cv_snprintf_useful_ret)
])
-test x"$have_asprintf" != x"yes" -a x"$ac_cv_snprintf_useful_ret" != x"yes" && \
- AC_MSG_ERROR(No asprintf and no snprintf returning required space!)
AC_ARG_ENABLE(unicode-tables,
AS_HELP_STRING([--disable-unicode-tables], [Disable Unicode tables]))
diff --git a/src/of_asprintf.m b/src/of_asprintf.m
index d336e56d..eb795c54 100644
--- a/src/of_asprintf.m
+++ b/src/of_asprintf.m
@@ -99,17 +99,43 @@ OF_CONSTRUCTOR()
static int
vasprintf(char **string, const char *format, va_list arguments)
{
- int length;
+ int expectedLength, length;
va_list argumentsCopy;
va_copy(argumentsCopy, arguments);
- if ((length = vsnprintf(NULL, 0, format, argumentsCopy)) < 0)
- return length;
- if ((*string = malloc((size_t)length + 1)) == NULL)
+ expectedLength = vsnprintf(NULL, 0, format, argumentsCopy);
+ if (expectedLength == -1)
+ /*
+ * We have no way to know how large it is. Let's try 64 KB and
+ * hope.
+ */
+ expectedLength = 65535;
+
+ if ((*string = malloc((size_t)expectedLength + 1)) == NULL)
+ return -1;
+
+ length = vsnprintf(*string, (size_t)expectedLength + 1,
+ format, arguments);
+
+ if (length == -1 || length > expectedLength) {
+ free(*string);
+ *string = NULL;
return -1;
+ }
+
+ /*
+ * In case we could not determine the size, resize to the actual size
+ * needed, but ignore any failure to do so.
+ */
+ if (length < expectedLength) {
+ char *resized;
+
+ if ((resized = realloc(*string, length + 1)) != NULL)
+ *string = resized;
+ }
- return vsnprintf(*string, (size_t)length + 1, format, arguments);
+ return length;
}
static int
@@ -551,6 +577,9 @@ formatConversionSpecifierState(struct context *ctx)
}
#ifndef HAVE_ASPRINTF_L
+ if (tmpLen == -1)
+ return false;
+
/*
* If there's no asprintf_l, we have no other choice than to
* use this ugly hack to replace the locale's decimal point