aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2026-04-29 14:00:08 +0200
committerWerner Koch <[email protected]>2026-04-29 14:00:08 +0200
commitf7ded3ce666ca8e27226dfa05b1e6b8636728441 (patch)
tree9e856de5844763ca1869332ecca7817a8ade380b /src
parentFix out-of-bounds read in vfnameconcat. (diff)
downloadlibgpg-error-f7ded3ce666ca8e27226dfa05b1e6b8636728441.tar.gz
libgpg-error-f7ded3ce666ca8e27226dfa05b1e6b8636728441.zip
Fix possible stack overflow in es_printf for %.100f format.
* configure.ac: Add test for snprintf. * src/gpgrt-int.h: Do not re-map snprintf if KEEP_SYSTEM_SNPRINTF is defined. * src/estream-printf.c (KEEP_SYSTEM_SNPRINTF): Define. (pr_float): Increase static buffer size. Use snprintf for long double. * tests/t-printf.c: Include float.h. (check_large_float): New. -- GnuPG-bug-id: 8240 Reported-by: Dirk Mueller <[email protected]> (AI)
Diffstat (limited to 'src')
-rw-r--r--src/estream-printf.c26
-rw-r--r--src/gpgrt-int.h4
2 files changed, 27 insertions, 3 deletions
diff --git a/src/estream-printf.c b/src/estream-printf.c
index 8e71db7..058ca71 100644
--- a/src/estream-printf.c
+++ b/src/estream-printf.c
@@ -71,6 +71,7 @@
*/
+#define KEEP_SYSTEM_SNPRINTF 1 /* Disable our snprintf re-mapping here. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -1073,7 +1074,7 @@ pr_float (estream_printf_out_t outfnc, void *outfncarg,
int use_dbl = 0;
#endif
double afloat;
- char numbuf[350];
+ char numbuf[450]; /* See comment above the sprintf. */
char formatstr[20];
char *p, *pend;
size_t n;
@@ -1129,9 +1130,30 @@ pr_float (estream_printf_out_t outfnc, void *outfncarg,
if ((arg->flags & FLAG_ALT_CONV))
*--p = '#';
*--p = '%';
+
+ /* On the size of NUMBUF: A double value (e.g. DBL_MAX) can have up
+ * to 309 decimal digits before the decimal point. When formatted
+ * with a precision of 100 (`%.100f`), the resulting string can have
+ * up to 411 characters (309 integer digits + 1 decimal point + 100
+ * fractional digits + 1 nul). With long double it is worse and in
+ * theory we should not use a static buffer but allocate a large
+ * one. However, platforms with support for long double will very
+ * likley also support snprintf which can then be used to throw an
+ * error on truncation. */
#ifdef HAVE_LONG_DOUBLE
if (use_dbl)
- sprintf (numbuf, p, adblfloat);
+ {
+# ifdef HAVE_SNPRINTF
+ rc = snprintf (numbuf, sizeof numbuf, p, adblfloat);
+# else
+ rc = -1; /* Not supported - should not happen. */
+# endif
+ if (rc < 0 || rc >= sizeof numbuf)
+ {
+ _set_errno (EINVAL);
+ return -1;
+ }
+ }
else
#endif /*HAVE_LONG_DOUBLE*/
sprintf (numbuf, p, afloat);
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index f67eec7..d373435 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -480,9 +480,11 @@ const char *_gpgrt_fname_get (gpgrt_stream_t stream);
#include "estream-printf.h"
-/* Make sure we always use our snprintf */
+/* Make sure we always use our snprintf (except for estream-printf.c) */
+#ifndef KEEP_SYSTEM_SNPRINTF
#undef snprintf
#define snprintf _gpgrt_estream_snprintf
+#endif
#if HAVE_W32_SYSTEM