[dovecot-cvs] dovecot: Require C99 compatible vsnprintf(). Removed printf_stri...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jun 11 02:21:34 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/09415e6a0892
changeset: 5681:09415e6a0892
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jun 11 02:21:30 2007 +0300
description:
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
replaced the code with printf_format_fix*() and vsnprintf().

diffstat:

11 files changed, 155 insertions(+), 484 deletions(-)
AUTHORS                      |   14 -
configure.in                 |   31 +++
src/lib/Makefile.am          |    2 
src/lib/failures.c           |   13 -
src/lib/printf-format-fix.c  |   89 ++++++-----
src/lib/printf-format-fix.h  |   11 +
src/lib/printf-upper-bound.c |  326 ------------------------------------------
src/lib/printf-upper-bound.h |   10 -
src/lib/str.c                |   32 +---
src/lib/strfuncs.c           |  109 ++++++--------
src/lib/strfuncs.h           |    2 

diffs (truncated from 830 to 300 lines):

diff -r 7577fb89916a -r 09415e6a0892 AUTHORS
--- a/AUTHORS	Mon Jun 11 02:16:59 2007 +0300
+++ b/AUTHORS	Mon Jun 11 02:21:30 2007 +0300
@@ -14,20 +14,6 @@ at Carnegie Mellon University (http://ww
 at Carnegie Mellon University (http://www.cmu.edu/computing/).
 (src/lib/base64.c, src/lib/utc-mktime.c)
 
-GLib Team (src/lib/printf-upper-bound.c)
----------
-Shawn T. Amundson  <amundson at gimp.org>
-Jeff Garzik        <jgarzik at pobox.com>
-Raja R Harinath    <harinath at cs.umn.edu>
-Tim Janik          <timj at gtk.org>
-Elliot Lee         <sopwith at redhat.com>
-Tor Lillqvist      <tml at iki.fi>
-Paolo Molaro       <lupus at debian.org>
-Havoc Pennington   <hp at pobox.com>
-Manish Singh       <yosh at gimp.org>
-Owen Taylor        <otaylor at gtk.org>
-Sebastian Wilhelmi <wilhelmi at ira.uka.de>
-
 Simon Tatham (src/imap/imap-thread.c merge sorting)
 
 Vaclav Haisman <v.haisman at sh.cvut.cz> (src/lib/ioloop-kqueue.c)
diff -r 7577fb89916a -r 09415e6a0892 configure.in
--- a/configure.in	Mon Jun 11 02:16:59 2007 +0300
+++ b/configure.in	Mon Jun 11 02:21:30 2007 +0300
@@ -433,7 +433,7 @@ fi
 
 dnl * after -lsocket and -lnsl tests, inet_aton() may be in them
 AC_CHECK_FUNCS(fcntl flock lockf inet_aton sigaction getpagesize madvise \
-               strcasecmp stricmp vsnprintf vsyslog writev pread \
+               strcasecmp stricmp vsyslog writev pread \
 	       setrlimit setproctitle seteuid setreuid setegid setresgid \
 	       strtoull strtouq setpriority quotactl getmntent kqueue kevent \
 	       getrusage backtrace_symbols walkcontext dirfd \
@@ -1311,6 +1311,35 @@ AC_TRY_COMPILE([
 ])
 
 dnl ***
+dnl *** C99 vsnprintf()?
+dnl ***
+
+AC_CACHE_CHECK([for C99 vsnprintf()],c99_vsnprintf,[
+  AC_RUN_IFELSE([AC_LANG_SOURCE([[
+  #include <stdio.h>
+  #include <stdarg.h>
+  static int f(const char *fmt, ...) {
+    va_list args;
+    char buf[13];
+    int ret;
+
+    va_start(args, fmt);
+    ret = vsnprintf(buf, 11, fmt, args) != 12 || buf[11-1] != '\0';
+    va_end(args);
+    return ret;
+  }
+  int main() {
+    return f("hello %s%d", "world", 1);
+  }]])],
+  [c99_vsnprintf=yes],
+  [c99_vsnprintf=no],
+  [])
+])
+if test $c99_vsnprintf = no; then
+  AC_ERROR([You don't appear to have C99 compatible vsnprintf() call])
+fi
+
+dnl ***
 dnl *** va_copy checks (from GLIB)
 dnl ***
 
diff -r 7577fb89916a -r 09415e6a0892 src/lib/Makefile.am
--- a/src/lib/Makefile.am	Mon Jun 11 02:16:59 2007 +0300
+++ b/src/lib/Makefile.am	Mon Jun 11 02:21:30 2007 +0300
@@ -67,7 +67,6 @@ liblib_a_SOURCES = \
 	ostream-crlf.c \
 	primes.c \
 	printf-format-fix.c \
-	printf-upper-bound.c \
 	process-title.c \
 	randgen.c \
 	read-full.c \
@@ -148,7 +147,6 @@ headers = \
 	ostream-internal.h \
 	primes.h \
 	printf-format-fix.h \
-	printf-upper-bound.h \
 	process-title.h \
 	randgen.h \
 	read-full.h \
diff -r 7577fb89916a -r 09415e6a0892 src/lib/failures.c
--- a/src/lib/failures.c	Mon Jun 11 02:16:59 2007 +0300
+++ b/src/lib/failures.c	Mon Jun 11 02:21:30 2007 +0300
@@ -83,7 +83,7 @@ default_handler(const char *prefix, FILE
 
 	if (recursed == 2) {
 		/* we're being called from some signal handler, or
-		   printf_format_fix() killed us again */
+		   printf_format_fix_unsafe() killed us again */
 		return -1;
 	}
 
@@ -98,9 +98,8 @@ default_handler(const char *prefix, FILE
 
 	VA_COPY(args2, args);
 
-	t_push();
 	if (recursed == 2) {
-		/* printf_format_fix() probably killed us last time,
+		/* printf_format_fix_unsafe() probably killed us last time,
 		   just write the format now. */
 
 		fputs("recursed: ", f);
@@ -114,13 +113,10 @@ default_handler(const char *prefix, FILE
 		errno = old_errno;
 
 		/* make sure there's no %n in there and fix %m */
-		(void)printf_format_fix(&format);
-		vfprintf(f, format, args2);
+		vfprintf(f, printf_format_fix_unsafe(format), args2);
 	}
 
 	fputc('\n', f);
-
-	t_pop();
 
 	errno = old_errno;
 	recursed--;
@@ -290,8 +286,7 @@ syslog_handler(int level, const char *fo
 
 	/* make sure there's no %n in there. vsyslog() supports %m, but since
 	   we'll convert it ourself anyway, we might as well it */
-	(void)printf_format_fix(&format);
-	vsyslog(level, format, args);
+	vsyslog(level, printf_format_fix_unsafe(format), args);
 	recursed--;
 
 	return 0;
diff -r 7577fb89916a -r 09415e6a0892 src/lib/printf-format-fix.c
--- a/src/lib/printf-format-fix.c	Mon Jun 11 02:16:59 2007 +0300
+++ b/src/lib/printf-format-fix.c	Mon Jun 11 02:21:30 2007 +0300
@@ -3,68 +3,81 @@
 #include "lib.h"
 #include "printf-format-fix.h"
 
-static const char *fix_format_real(const char *fmt, const char *p)
+static const char *
+fix_format_real(const char *fmt, const char *p, unsigned int *len_r)
 {
 	const char *errstr;
 	char *buf;
-	size_t pos, alloc, errlen;
+	unsigned int len1, len2, len3;
+
+	i_assert((size_t)(p - fmt) < INT_MAX);
 
 	errstr = strerror(errno);
-	errlen = strlen(errstr);
 
-	pos = (size_t) (p-fmt);
-	i_assert(pos < SSIZE_T_MAX);
+	/* we'll assume that there's only one %m in the format string.
+	   this simplifies the code and there's really no good reason to have
+	   it multiple times. */
+	len1 = p - fmt;
+	len2 = strlen(errstr);
+	len3 = strlen(fmt + 1);
 
-	alloc = pos + errlen + 128;
-	buf = t_buffer_get(alloc);
+	/* @UNSAFE */
+	buf = t_buffer_get(len1 + len2 + len3 + 1);
+	memcpy(buf, fmt, len1);
+	memcpy(buf + len1, errstr, len2);
+	memcpy(buf + len1 + len2, p + 1, len3);
+	buf[len1 + len2 + len3] = '\0';
 
-	memcpy(buf, fmt, pos);
-
-	while (*p != '\0') {
-		if (*p == '%' && p[1] == 'm') {
-			if (pos+errlen+1 > alloc) {
-				alloc += errlen+1 + 128;
-				buf = t_buffer_get(alloc);
-			}
-
-			memcpy(buf+pos, errstr, errlen);
-			pos += errlen;
-			p += 2;
-		} else {
-			/* p + \0 */
-			if (pos+2 > alloc) {
-				alloc += 128;
-				buf = t_buffer_get(alloc);
-			}
-
-			buf[pos++] = *p;
-			p++;
-		}
-	}
-
-	buf[pos++] = '\0';
-	t_buffer_alloc(pos);
+	*len_r = len1 + len2 + len3;
 	return buf;
 }
 
-bool printf_format_fix(const char **format)
+static const char *
+printf_format_fix_noalloc(const char *format, unsigned int *len_r)
 {
 	const char *p;
 
-	for (p = *format; *p != '\0'; p++) {
+	for (p = format; *p != '\0'; p++) {
 		if (*p++ == '%') {
 			switch (*p) {
 			case 'n':
 				i_panic("%%n modifier used");
 			case 'm':
-				*format = fix_format_real(*format, p-1);
-				return TRUE;
+				return fix_format_real(format, p-1, len_r);
 			case '\0':
 				i_panic("%% modifier missing");
 			}
 		}
 	}
 
-	return FALSE;
+	*len_r = p - format;
+	return format;
 }
 
+const char *printf_format_fix_get_len(const char *format, unsigned int *len_r)
+{
+	const char *ret;
+
+	ret = printf_format_fix_noalloc(format, len_r);
+	if (ret != format)
+		t_buffer_alloc(*len_r + 1);
+	return ret;
+}
+
+const char *printf_format_fix(const char *format)
+{
+	const char *ret;
+	unsigned int len;
+
+	ret = printf_format_fix_noalloc(format, &len);
+	if (ret != format)
+		t_buffer_alloc(len + 1);
+	return ret;
+}
+
+const char *printf_format_fix_unsafe(const char *format)
+{
+	unsigned int len;
+
+	return printf_format_fix_noalloc(format, &len);
+}
diff -r 7577fb89916a -r 09415e6a0892 src/lib/printf-format-fix.h
--- a/src/lib/printf-format-fix.h	Mon Jun 11 02:16:59 2007 +0300
+++ b/src/lib/printf-format-fix.h	Mon Jun 11 02:21:30 2007 +0300
@@ -2,7 +2,14 @@
 #define __PRINTF_FORMAT_FIX_H
 
 /* Replaces %m in format with strerror(errno) and panics if %n modifier is
-   used. Returns TRUE if format was modified. */
-bool printf_format_fix(const char **format);
+   used. If the format string was modified, it's returned from data stack. */
+const char *printf_format_fix(const char *format) __attr_format_arg__(1);
+/* Like printf_format_fix(), except return also the format string's length. */
+const char *printf_format_fix_get_len(const char *format, unsigned int *len_r)
+	__attr_format_arg__(1);
+/* Like printf_format_fix(), except the format string is written to data
+   stack without actually allocating it. Data stack must not be used until
+   format string is no longer needed. */
+const char *printf_format_fix_unsafe(const char *format) __attr_format_arg__(1);
 
 #endif
diff -r 7577fb89916a -r 09415e6a0892 src/lib/printf-upper-bound.c
--- a/src/lib/printf-upper-bound.c	Mon Jun 11 02:16:59 2007 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,326 +0,0 @@
-/*
-    Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
-    Modified by the GLib Team and others 1997-1999.
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-  
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
-    Library General Public License for more details.
-  


More information about the dovecot-cvs mailing list