changeset 837:ec6dd72cb8e3 HEAD

Use vsnprintf() always when possible, even if we went through the upper_bound function. DEBUG message in data stack might have sometimes caused an infinite loop. Made sure infinite loops don't happen anymore with failure handlers. str_printfa() didn't handle %m. Made my_vsyslog() a lot simpler, since t_strdup_printf() is now safe enough to call in failure handler.
author Timo Sirainen <tss@iki.fi>
date Sun, 22 Dec 2002 08:25:50 +0200
parents eefa28ef9646
children a6cd073c5283
files src/lib/compat.c src/lib/data-stack.c src/lib/failures.c src/lib/str.c src/lib/strfuncs.c
diffstat 5 files changed, 123 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/compat.c	Sun Dec 22 00:39:15 2002 +0200
+++ b/src/lib/compat.c	Sun Dec 22 08:25:50 2002 +0200
@@ -72,30 +72,7 @@
 #ifndef HAVE_VSYSLOG
 void my_vsyslog(int priority, const char *format, va_list args)
 {
-	const char *str;
-	char buf[1024];
-
-#ifdef HAVE_VSNPRINTF
-	int ret;
-
-	ret = vsnprintf(buf, sizeof(buf), format, args);
-	if (ret < 0 || (size_t)ret >= sizeof(buf))
-		buf[sizeof(buf)-1] = '\0';
-	str = buf;
-#else
-        va_list args2;
-
-	VA_COPY(args2, args);
-
-	if (printf_string_upper_bound(format, args) < sizeof(buf)) {
-		vsprintf(buf, format, args);
-		str = buf;
-	} else {
-		/* this may not be safe but not choice really.. */
-		str = t_strdup_vprintf(format, args2);
-	}
-#endif
-	syslog(priority, "%s", str);
+	syslog(priority, "%s", t_strdup_vprintf(format, args));
 }
 #endif
 
--- a/src/lib/data-stack.c	Sun Dec 22 00:39:15 2002 +0200
+++ b/src/lib/data-stack.c	Sun Dec 22 08:25:50 2002 +0200
@@ -198,6 +198,9 @@
 {
 	StackBlock *block;
         void *ret;
+#ifdef DEBUG
+	int warn = FALSE;
+#endif
 
 	if (size == 0)
 		return NULL;
@@ -233,7 +236,7 @@
 	} else {
 		block = mem_block_alloc(size);
 #ifdef DEBUG
-		i_warning("Growing data stack with: %"PRIuSIZE_T, block->size);
+		warn = TRUE;
 #endif
 	}
 
@@ -245,7 +248,16 @@
 	current_block->next = block;
 	current_block = block;
 
-        return STACK_BLOCK_DATA(current_block);
+	ret = STACK_BLOCK_DATA(current_block);
+#ifdef DEBUG
+	if (warn) {
+		/* warn later, so that if i_warning() wants to allocate more
+		   memory we don't go to infinite loop */
+		i_warning("Growing data stack with: %"PRIuSIZE_T, block->size);
+	}
+#endif
+
+        return ret;
 }
 
 void *t_malloc(size_t size)
--- a/src/lib/failures.c	Sun Dec 22 00:39:15 2002 +0200
+++ b/src/lib/failures.c	Sun Dec 22 08:25:50 2002 +0200
@@ -78,26 +78,56 @@
 	}
 }
 
+static void default_handler(const char *prefix, const char *format,
+			    va_list args)
+{
+	static int recursed = 0;
+	int old_errno = errno;
+
+	if (recursed == 2) {
+		/* we're being called from some signal handler, or
+		   printf_string_upper_bound() killed us again */
+		return;
+	}
+
+	recursed++;
+
+	if (log_fd == NULL)
+		log_fd = stderr;
+
+	if (recursed == 2) {
+		/* write without fixing format, that probably killed us
+		   last time. */
+
+		/* make sure there's no %n in there */
+                (void)printf_string_upper_bound(format, args);
+		vfprintf(log_fd, format, args);
+		fputs(" - recursed!", log_fd);
+	} else {
+		write_prefix(log_fd);
+
+		fputs(prefix, log_fd);
+		format = printf_string_fix_format(format);
+		/* make sure there's no %n in there */
+                (void)printf_string_upper_bound(format, args);
+		vfprintf(log_fd, format, args);
+	}
+
+	fputc('\n', log_fd);
+
+	errno = old_errno;
+	recursed--;
+}
+
 static void default_panic_handler(const char *format, va_list args)
 {
-	if (log_fd == NULL) log_fd = stderr;
-	write_prefix(log_fd);
-
-	fputs("Panic: ", log_fd);
-	vfprintf(log_fd, printf_string_fix_format(format), args);
-	fputc('\n', log_fd);
-
+	default_handler("Panic: ", format, args);
 	abort();
 }
 
 static void default_fatal_handler(int status, const char *format, va_list args)
 {
-	if (log_fd == NULL) log_fd = stderr;
-	write_prefix(log_fd);
-
-	fputs("Fatal: ", log_fd);
-	vfprintf(log_fd, printf_string_fix_format(format), args);
-	fputc('\n', log_fd);
+	default_handler("Fatal: ", format, args);
 
 	if (fflush(log_fd) < 0 && status == FATAL_DEFAULT)
 		status = FATAL_LOGWRITE;
@@ -109,14 +139,7 @@
 {
 	int old_errno = errno;
 
-	if (log_fd == NULL) log_fd = stderr;
-	write_prefix(log_fd);
-
-	t_push();
-	fputs("Error: ", log_fd);
-	vfprintf(log_fd, printf_string_fix_format(format), args);
-        fputc('\n', log_fd);
-	t_pop();
+	default_handler("Error: ", format, args);
 
 	if (fflush(log_fd) < 0)
 		exit(FATAL_LOGWRITE);
@@ -128,14 +151,7 @@
 {
 	int old_errno = errno;
 
-	if (log_fd == NULL) log_fd = stderr;
-	write_prefix(log_fd);
-
-	t_push();
-	fputs("Warning: ", log_fd);
-	vfprintf(log_fd, printf_string_fix_format(format), args);
-	fputc('\n', log_fd);
-	t_pop();
+	default_handler("Warning: ", format, args);
 
 	if (fflush(log_fd) < 0)
 		exit(FATAL_LOGWRITE);
@@ -147,15 +163,9 @@
 {
 	int old_errno = errno;
 
-	if (log_info_fd == NULL) log_info_fd = stderr;
-	write_prefix(log_info_fd);
+	default_handler("Info: ", format, args);
 
-	t_push();
-	vfprintf(log_info_fd, printf_string_fix_format(format), args);
-	fputc('\n', log_info_fd);
-	t_pop();
-
-	if (fflush(log_info_fd) < 0)
+	if (fflush(log_fd) < 0)
 		exit(FATAL_LOGWRITE);
 
 	errno = old_errno;
@@ -250,31 +260,47 @@
         info_handler = func;
 }
 
+static void syslog_handler(int level, const char *format, va_list args)
+{
+	static int recursed = 0;
+
+	if (recursed != 0)
+		return;
+
+	recursed++;
+
+	/* make sure there's no %n in there */
+	(void)printf_string_upper_bound(format, args);
+
+	vsyslog(level, format, args);
+	recursed--;
+}
+
 void i_syslog_panic_handler(const char *fmt, va_list args)
 {
-	vsyslog(LOG_CRIT, fmt, args);
+	syslog_handler(LOG_CRIT, fmt, args);
         abort();
 }
 
 void i_syslog_fatal_handler(int status, const char *fmt, va_list args)
 {
-	vsyslog(LOG_CRIT, fmt, args);
+	syslog_handler(LOG_CRIT, fmt, args);
 	exit(status);
 }
 
 void i_syslog_error_handler(const char *fmt, va_list args)
 {
-	vsyslog(LOG_ERR, fmt, args);
+	syslog_handler(LOG_ERR, fmt, args);
 }
 
 void i_syslog_warning_handler(const char *fmt, va_list args)
 {
-	vsyslog(LOG_WARNING, fmt, args);
+	syslog_handler(LOG_WARNING, fmt, args);
 }
 
 void i_syslog_info_handler(const char *fmt, va_list args)
 {
-	vsyslog(LOG_INFO, fmt, args);
+	syslog_handler(LOG_INFO, fmt, args);
 }
 
 void i_set_failure_syslog(const char *ident, int options, int facility)
--- a/src/lib/str.c	Sun Dec 22 00:39:15 2002 +0200
+++ b/src/lib/str.c	Sun Dec 22 08:25:50 2002 +0200
@@ -121,12 +121,25 @@
 void str_vprintfa(String *str, const char *fmt, va_list args)
 {
 	char *buf;
-	size_t len;
+	int ret;
+	size_t len, append_len;
 
 	len = buffer_get_used_size(str);
 
-	buf = buffer_append_space(str, printf_string_upper_bound(fmt, args));
-	len += vsprintf(buf, fmt, args);
+	fmt = printf_string_fix_format(fmt);
+	append_len = printf_string_upper_bound(fmt, args);
+
+	buf = buffer_append_space(str, append_len);
+
+#ifdef HAVE_VSNPRINTF
+	ret = vsnprintf(buf, append_len, fmt, args);
+	i_assert(ret >= 0 && (size_t)ret <= append_len);
+#else
+	ret = vsprintf(buf, fmt, args);
+	i_assert(ret >= 0);
+#endif
+
+	len += ret;
 
 	buffer_set_used_size(str, len);
 }
--- a/src/lib/strfuncs.c	Sun Dec 22 00:39:15 2002 +0200
+++ b/src/lib/strfuncs.c	Sun Dec 22 08:25:50 2002 +0200
@@ -389,44 +389,30 @@
 
 int i_snprintf(char *dest, size_t max_chars, const char *format, ...)
 {
-#ifdef HAVE_VSNPRINTF
+#ifndef HAVE_VSNPRINTF
+	char *buf;
+#endif
 	va_list args;
+	ssize_t len;
 	int ret;
 
-	i_assert(dest != NULL);
 	i_assert(max_chars < INT_MAX);
-	i_assert(format != NULL);
-
-	t_push();
-	va_start(args, format);
-	ret = vsnprintf(dest, max_chars,
-			printf_string_fix_format(format), args);
-	va_end(args);
-	t_pop();
-
-	if (ret < 0 || (size_t)ret >= max_chars) {
-		dest[max_chars-1] = '\0';
-		return -1;
-	}
-
-	return 0;
-#else
-	char *buf;
-	va_list args;
-        int len, ret;
-
-	i_assert(dest != NULL);
-	i_assert(max_chars < INT_MAX);
-	i_assert(format != NULL);
 
 	t_push();
 
 	va_start(args, format);
 	format = printf_string_fix_format(format);
-	buf = t_buffer_get(printf_string_upper_bound(format, args));
+	len = printf_string_upper_bound(format, args);
 	va_end(args);
 
+	i_assert(len >= 0);
+
+#ifdef HAVE_VSNPRINTF
+	len = vsnprintf(dest, max_chars, format, args);
+#else
+	buf = t_buffer_get(len);
 	len = vsprintf(buf, format, args);
+#endif
 	if (len < 0) {
 		/* some error occured */
 		len = 0;
@@ -439,12 +425,13 @@
 		ret = 0;
 	}
 
-        memcpy(dest, buf, len);
+#ifndef HAVE_VSNPRINTF
+	memcpy(dest, buf, len);
+#endif
 	dest[len] = '\0';
 
 	t_pop();
 	return ret;
-#endif
 }
 
 #define STRDUP_CORE(alloc_func, str) STMT_START { \
@@ -608,7 +595,8 @@
 		    ALLOC_FUNC alloc_func, Pool pool)
 {
         va_list temp_args;
-        char *ret;
+	char *ret;
+	size_t len;
 
 	if (format == NULL)
 		return NULL;
@@ -617,8 +605,14 @@
 
 	VA_COPY(temp_args, args);
 
-        ret = alloc_func(pool, printf_string_upper_bound(format, args));
+	len = printf_string_upper_bound(format, args);
+        ret = alloc_func(pool, len);
+
+#ifdef HAVE_VSNPRINTF
+	vsnprintf(ret, len, format, args);
+#else
 	vsprintf(ret, format, args);
+#endif
 
 	va_end(temp_args);