[PATCH] check for broken snprintf + workaround
Oswald Buddenhagen
ossi at kde.org
Mon Dec 9 13:21:29 GMT 2002
heya,
as a followup to my bitching about constructs like
snprintf(buf, sizeof(buf) - 1, [...]);
buf[sizeof(buf)-1] = 0;
all across the kde code i implemented a rather paranoid configure
check + centralized this ugly workaround.
there are two known breakages:
* if snprintf overflows (like the linux libc4 libbsd one that simply
calls sprintf) the test will bail.
* if snprintf does not null-terminate in the overflow case (like m$ vc++
<= 6 - just in case the native windoze port becomes reality some day :),
the calls are substituted with wrappers which add the null.
my only concern is the #define [v]snprintf that might collide with other
snprintfs than the libc one (too bad that c does not provide aliasing at
the language level). i know that sprintf would collide, but am not aware
of any snprintf()s - somebody?
at this occasion i also removed the old-style varargs stuff, as kde
won't run with it in any case.
greetings
--
Hi! I'm a .signature virus! Copy me into your ~/.signature, please!
--
Chaos, panic, and disorder - my work here is done.
-------------- next part --------------
Index: admin/acinclude.m4.in
===================================================================
RCS file: /home/kde/kde-common/admin/acinclude.m4.in,v
retrieving revision 2.306
diff -u -r2.306 acinclude.m4.in
--- admin/acinclude.m4.in 5 Dec 2002 20:30:26 -0000 2.306
+++ admin/acinclude.m4.in 9 Dec 2002 12:46:22 -0000
@@ -754,19 +754,62 @@
])
AC_CHECK_FUNCS([vsnprintf snprintf])
+if test x$ac_cv_func_snprintf = xyes; then
+ AC_CACHE_CHECK([whether snprintf works], kde_cv_snprintf_ok, [
+ AC_TRY_RUN([
+#include <stdio.h>
+
+int main()
+{
+ char buf[11];
+
+ buf[10] = 'O';
+ snprintf(buf, 10, "0123456789");
+ /* extra paranoia */
+ snprintf(buf, 10, "01234%s", "56789");
+ snprintf(buf, 10, "01234%d", 56789);
+ if (buf[10] != 'O')
+ return 1; /* buffer can overflow */
+ if (buf[9])
+ return 83; /* buffer not null-terminated */
+ return 0;
+}],
+ [kde_cv_snprintf_ok=yes],
+ [if test x$ac_result = x83; then
+ kde_cv_snprintf_ok=mostly
+ else
+ kde_cv_snprintf_ok=no
+ fi],
+ [kde_cv_snprintf_ok=unknown]
+ )
+ ])
+ if test x$kde_cv_snprintf_ok = xno; then
+ AC_MSG_ERROR([The snprintf() implementation in your c library
+is seriously broken. Upgrade it and try again.
+Please inform security at kde.org that this happened. Don't forget to report the
+exact description of the build environment.])
+ elif test x$kde_cv_snprintf_ok != xyes; then
+ if test x$kde_cv_snprintf_ok = xunknown; then
+ AC_MSG_WARN([Cannot test whether snprintf() works (cross-compile)])
+ fi
+ AC_DEFINE(SNPRINTF_BROKEN, 1, [Define this if snprintf() does not always null-terminate])
+ fi
+fi
+
+AH_VERBATIM(_SNPRINTF,[
+
+#ifdef SNPRINTF_BROKEN
+# define snprintf snprintf_wrapper
+# define vsnprintf vsnprintf_wrapper
+#endif
-AH_VERBATIM(_TRU64,[
/*
* On HP-UX, the declaration of vsnprintf() is needed every time !
*/
-#if !defined(HAVE_VSNPRINTF) || defined(hpux)
-#if __STDC__
+#if !defined(HAVE_VSNPRINTF) || defined(SNPRINTF_BROKEN) || defined(hpux)
#include <stdarg.h>
#include <stdlib.h>
-#else
-#include <varargs.h>
-#endif
#ifdef __cplusplus
extern "C"
#endif
Index: kdecore/vsnprintf.c
===================================================================
RCS file: /home/kde/kdelibs/kdecore/vsnprintf.c,v
retrieving revision 1.6
diff -u -r1.6 vsnprintf.c
--- kdecore/vsnprintf.c 19 Jan 2002 16:11:39 -0000 1.6
+++ kdecore/vsnprintf.c 9 Dec 2002 12:46:22 -0000
@@ -1,4 +1,5 @@
#include "config.h"
+
#ifndef HAVE_VSNPRINTF
/*
@@ -34,12 +35,8 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
-#if __STDC__
#include <stdarg.h>
#include <stdlib.h>
-#else
-#include <varargs.h>
-#endif
#include <setjmp.h>
#ifndef roundup
@@ -104,15 +101,7 @@
}
int
-#if __STDC__
vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
-#else
-vsnprintf(str, n, fmt, ap)
- char *str;
- size_t n;
- char *fmt;
- char *ap;
-#endif
{
struct sigaction osa, nsa;
char *p;
@@ -140,31 +129,50 @@
}
int
-#if __STDC__
snprintf(char *str, size_t n, char const *fmt, ...)
-#else
-snprintf(str, n, fmt, va_alist)
- char *str;
- size_t n;
- char *fmt;
- va_dcl
-#endif
{
+ int r;
va_list ap;
-#if __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- return (vsnprintf(str, n, fmt, ap));
+ va_start(ap, fmt);
+ r = vsnprintf(str, n, fmt, ap);
va_end(ap);
+ return r;
}
+#elif defined(SNPRINTF_BROKEN)
+# undef snprintf
+# undef vsnprintf
-#endif
+int
+vsnprintf_wrapper(char *str, size_t n, char const *fmt, va_list ap)
+{
+ unsigned r;
+
+ r = vsnprintf(str, n, fmt, ap);
+ if (r >= n && n) /* catches both r == -1 and r >= n */
+ str[n - 1] = 0;
+ return r;
+}
+
+int
+snprintf_wrapper(char *str, size_t n, char const *fmt, ...)
+{
+ int r;
+ va_list ap;
+
+ va_start(ap, fmt);
+ r = vsnprintf_wrapper(str, n, fmt, ap);
+ va_end(ap);
+ return r;
+}
+
+#else
-/* ANSI C forbids en empty source file... */
+/* ANSI C forbids empty source files... */
static void dummy_func() {
dummy_func();
}
+
+#endif
+
More information about the kde-core-devel
mailing list