[dovecot-cvs] dovecot/src/lib printf-upper-bound.c,NONE,1.1 printf-upper-bound.h,NONE,1.1 Makefile.am,1.24,1.25 data-stack.c,1.12,1.13 failures.c,1.12,1.13 imem.c,1.4,1.5 imem.h,1.4,1.5 mempool-alloconly.c,1.13,1.14 mempool-datastack.c,1.2,1.3 Message-Id: <20021222070618.C5D342382C@danu.procontrol.fi>

cras at procontrol.fi cras at procontrol.fi
Sun Dec 22 09:06:18 EET 2002


Update of /home/cvs/dovecot/src/lib
In directory danu:/tmp/cvs-serv1084/src/lib

Modified Files:
	Makefile.am data-stack.c failures.c imem.c imem.h 
	mempool-alloconly.c mempool-datastack.c mempool-system.c str.c 
	strfuncs.c strfuncs.h 
Added Files:
	printf-upper-bound.c printf-upper-bound.h 
Log Message:
String function cleanups. Allocating 0 bytes of memory is treated as error
now, it could be an integer overflow. Moved printf_string_upper_bound() to  
it's own file, so strfuncs.c can be with MIT license.



--- NEW FILE: printf-upper-bound.c ---
/*
    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.
  
    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "lib.h"
#include "printf-upper-bound.h"

typedef union  _GDoubleIEEE754  GDoubleIEEE754;
#define G_IEEE754_DOUBLE_BIAS   (1023)
/* multiply with base2 exponent to get base10 exponent (nomal numbers) */
#define G_LOG_2_BASE_10         (0.30102999566398119521)
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
union _GDoubleIEEE754
{
  double v_double;
  struct {
    unsigned int mantissa_low : 32;
    unsigned int mantissa_high : 20;
    unsigned int biased_exponent : 11;
    unsigned int sign : 1;
  } mpn;
};
#elif G_BYTE_ORDER == G_BIG_ENDIAN
union _GDoubleIEEE754
{
  double v_double;
  struct {
    unsigned int sign : 1;
    unsigned int biased_exponent : 11;
    unsigned int mantissa_high : 20;
    unsigned int mantissa_low : 32;
  } mpn;
};
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
#error unknown ENDIAN type
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */

typedef struct
{
  unsigned int min_width;
  unsigned int precision;
  int alternate_format, zero_padding, adjust_left, locale_grouping;
  int add_space, add_sign, possible_sign, seen_precision;
  int mod_long, mod_extra_long;
} PrintfArgSpec;

#if (SIZEOF_LONG > 4) || (SIZEOF_VOID_P > 4)
#  define HONOUR_LONGS 1
#else
#  define HONOUR_LONGS 0
#endif

size_t printf_string_upper_bound(const char *format, va_list args)
{
  size_t len = 1;

  if (!format)
    return len;

  while (*format)
    {
      register char c = *format++;

      if (c != '%')
        len += 1;
      else /* (c == '%') */
        {
          PrintfArgSpec spec;
          int seen_l = FALSE, conv_done = FALSE;
          unsigned int conv_len = 0;

          memset(&spec, 0, sizeof(spec));
          do
            {
              c = *format++;
              switch (c)
                {
                  GDoubleIEEE754 u_double;
                  unsigned int v_uint;
                  int v_int;
                  const char *v_string;

                  /* beware of positional parameters
                   */
                case '$':
                  i_panic("unable to handle positional parameters (%%n$)");
                  break;

                  /* parse flags
                   */
                case '#':
                  spec.alternate_format = TRUE;
                  break;
                case '0':
                  spec.zero_padding = TRUE;
                  break;
                case '-':
                  spec.adjust_left = TRUE;
                  break;
                case ' ':
                  spec.add_space = TRUE;
                  break;
                case '+':
                  spec.add_sign = TRUE;
                  break;
                case '\'':
                  spec.locale_grouping = TRUE;
                  break;

                  /* parse output size specifications
                   */
                case '.':
                  spec.seen_precision = TRUE;
                  break;
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                  v_uint = c - '0';
                  c = *format;
                  while (c >= '0' && c <= '9')
                    {
                      format++;
                      v_uint = v_uint * 10 + (c - '0');
                      c = *format;
                    }
                  if (spec.seen_precision)
                    spec.precision = I_MAX (spec.precision, v_uint);
                  else
                    spec.min_width = I_MAX (spec.min_width, v_uint);
                  break;
                case '*':
                  v_int = va_arg (args, int);
                  if (spec.seen_precision)
                    {
                      /* forget about negative precision */
                      if (v_int >= 0)
                        spec.precision = I_MAX ((int)spec.precision, v_int);
                    }
                  else
                    {
                      if (v_int < 0)
                        {
                          v_int = - v_int;
                          spec.adjust_left = TRUE;
                        }
                      spec.min_width = I_MAX ((int)spec.min_width, v_int);
                    }
                  break;

                  /* parse type modifiers
                   */
                case 'h':
		  /* ignore */
                  break;
                case 'l':
                  if (!seen_l)
                    {
                      spec.mod_long = TRUE;
                      seen_l = TRUE;
                      break;
                    }
                  /* else, fall through */
                case 'L':
                  spec.mod_long = TRUE;
                  spec.mod_extra_long = TRUE;
                  break;

                  /* parse output conversions
                   */
                case '%':
                  conv_len += 1;
                  break;
                case 'o':
                  conv_len += 2;
                  /* fall through */
                case 'd':
                case 'i':
                  conv_len += 1; /* sign */
                  /* fall through */
                case 'u':
                  conv_len += 4;
                  /* fall through */
                case 'x':
                case 'X':
                  spec.possible_sign = TRUE;
                  conv_len += 10;
                  if (spec.mod_long && HONOUR_LONGS)
                    conv_len *= 2;
                  if (spec.mod_extra_long)
                    conv_len *= 2;
                  if (spec.mod_extra_long)
                    {
#if SIZEOF_LONG_LONG > 0
                      (void) va_arg (args, long long);
#else
		      i_panic("mod_extra_long not supported");
#endif
                    }
                  else if (spec.mod_long)
                    (void) va_arg (args, long);
                  else
                    (void) va_arg (args, int);
                  break;
                case 'A':
                case 'a':
                  /*          0x */
                  conv_len += 2;
                  /* fall through */
                case 'g':
                case 'G':
                case 'e':
                case 'E':
                case 'f':
                  spec.possible_sign = TRUE;
                  /*          n   .   dddddddddddddddddddddddd   E   +-  eeee */
                  conv_len += 1 + 1 + I_MAX (24, spec.precision) + 1 + 1 + 4;
                  if (spec.mod_extra_long)
                    i_panic("unable to handle long double");
#ifdef HAVE_LONG_DOUBLE
#error need to implement special handling for long double
#endif
                  u_double.v_double = va_arg (args, double);
                  /* %f can expand up to all significant digits before '.' (308) */
                  if (c == 'f' &&
                      u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047)
                    {
                      int exp = u_double.mpn.biased_exponent;

                      exp -= G_IEEE754_DOUBLE_BIAS;
                      exp = exp * G_LOG_2_BASE_10 + 1;
                      conv_len += exp;
                    }
                  /* some printf() implementations require extra padding for rounding */
                  conv_len += 2;
                  /* we can't really handle locale specific grouping here */
                  if (spec.locale_grouping)
                    conv_len *= 2;
                  break;
                case 'c':
                  conv_len += spec.mod_long ? MB_LEN_MAX : 1;
                  (void) va_arg (args, int);
                  break;
                case 's':
                  v_string = va_arg (args, char*);
                  if (!v_string)
                    conv_len += 8; /* hold "(null)" */
                  else if (spec.seen_precision)
                    conv_len += spec.precision;
                  else
                    conv_len += strlen (v_string);
                  conv_done = TRUE;
                  if (spec.mod_long)
                    i_panic("unable to handle wide char strings");
                  break;
                case 'p':
                  spec.alternate_format = TRUE;
                  conv_len += 10;
                  if (HONOUR_LONGS)
                    conv_len *= 2;
		  conv_done = TRUE;
		  (void) va_arg (args, void*);
                  break;

                  /* handle invalid cases
                   */
                case '\000':
                  /* no conversion specification, bad bad */
		  i_panic("Missing conversion specifier");
                  break;
                default:
                  i_panic("unable to handle `%c' while parsing format", c);
                  break;
                }
              conv_done |= conv_len > 0;
            }
          while (!conv_done);
          /* handle width specifications */
          conv_len = I_MAX (conv_len, I_MAX (spec.precision, spec.min_width));
          /* handle flags */
          conv_len += spec.alternate_format ? 2 : 0;
          conv_len += (spec.add_space || spec.add_sign || spec.possible_sign);
          /* finally done */
          len += conv_len;
        } /* else (c == '%') */
    } /* while (*format) */

  return len;
}

--- NEW FILE: printf-upper-bound.h ---
#ifndef __PRINTF_UPPER_BOUND_H
#define __PRINTF_UPPER_BOUND_H

/* Returns the maximum length of given format string when expanded.
   If the format is invalid, i_fatal() is called. */
size_t printf_string_upper_bound(const char *format, va_list args);

#endif

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- Makefile.am	21 Dec 2002 22:02:58 -0000	1.24
+++ Makefile.am	22 Dec 2002 07:06:16 -0000	1.25
@@ -36,6 +36,7 @@
 	ostream.c \
 	ostream-file.c \
 	primes.c \
+	printf-upper-bound.c \
 	process-title.c \
 	randgen.c \
 	restrict-access.c \
@@ -82,6 +83,7 @@
 	ostream.h \
 	ostream-internal.h \
 	primes.h \
+	printf-upper-bound.h \
 	process-title.h \
 	randgen.h \
 	restrict-access.h \

Index: data-stack.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/data-stack.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- data-stack.c	22 Dec 2002 06:25:50 -0000	1.12
+++ data-stack.c	22 Dec 2002 07:06:16 -0000	1.13
@@ -202,11 +202,8 @@
 	int warn = FALSE;
 #endif
 
-	if (size == 0)
-		return NULL;
-
-	if (size > MAX_ALLOC_SIZE)
-		i_panic("Trying to allocate too much memory");
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
 	/* reset t_buffer_get() mark - not really needed but makes it easier
 	   to notice if t_malloc() is called between t_buffer_get() and
@@ -277,6 +274,9 @@
 int t_try_realloc(void *mem, size_t size)
 {
 	size_t last_alloc_size;
+
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
 	last_alloc_size = current_frame_block->last_alloc_size[frame_pos];
 

Index: failures.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/failures.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- failures.c	22 Dec 2002 06:28:44 -0000	1.12
+++ failures.c	22 Dec 2002 07:06:16 -0000	1.13
@@ -27,6 +27,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "fd-close-on-exec.h"
+#include "printf-upper-bound.h"
 
 #include <stdio.h>
 #include <stdlib.h>

Index: imem.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/imem.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- imem.c	21 Dec 2002 13:08:49 -0000	1.4
+++ imem.c	22 Dec 2002 07:06:16 -0000	1.5
@@ -78,12 +78,6 @@
         return p_strdup_vprintf(default_pool, format, args);
 }
 
-void i_strdup_replace(char **dest, const char *str)
-{
-	p_free(default_pool, *dest);
-        *dest = p_strdup(default_pool, str);
-}
-
 char *i_strconcat(const char *str1, ...)
 {
 	va_list args;
@@ -93,9 +87,13 @@
 
 	va_start(args, str1);
 
-	temp = temp_strconcat(str1, args, &len);
-        ret = p_malloc(default_pool, len);
-        memcpy(ret, temp, len);
+	temp = _vstrconcat(str1, args, &len);
+	if (temp == NULL)
+		ret = NULL;
+	else {
+		ret = p_malloc(default_pool, len);
+		memcpy(ret, temp, len);
+	}
 
 	va_end(args);
         return ret;

Index: imem.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/imem.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- imem.h	2 Dec 2002 13:45:58 -0000	1.4
+++ imem.h	22 Dec 2002 07:06:16 -0000	1.5
@@ -17,7 +17,6 @@
 char *i_strndup(const char *str, size_t max_chars);
 char *i_strdup_printf(const char *format, ...) __attr_format__(1, 2);
 char *i_strdup_vprintf(const char *format, va_list args);
-void i_strdup_replace(char **dest, const char *str);
 
 char *i_strconcat(const char *str1, ...); /* NULL terminated */
 

Index: mempool-alloconly.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/mempool-alloconly.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- mempool-alloconly.c	21 Dec 2002 13:12:16 -0000	1.13
+++ mempool-alloconly.c	22 Dec 2002 07:06:16 -0000	1.14
@@ -168,6 +168,9 @@
 	AlloconlyPool *apool = (AlloconlyPool *) pool;
 	PoolAlloc *alloc;
 
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
+
 	size = MEM_ALIGN(size);
 
 	if (apool->block->left < size + SIZEOF_POOLALLOC) {
@@ -221,6 +224,9 @@
 	PoolAlloc *alloc;
 	unsigned char *new_mem;
 	size_t old_size;
+
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
 	if (mem == NULL) {
 		alloc = NULL;

Index: mempool-datastack.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/mempool-datastack.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- mempool-datastack.c	18 Dec 2002 15:15:41 -0000	1.2
+++ mempool-datastack.c	22 Dec 2002 07:06:16 -0000	1.3
@@ -28,8 +28,6 @@
 
 #include <stdlib.h>
 
-#define MAX_ALLOC_SIZE SSIZE_T_MAX
-
 typedef struct {
 	union {
 		size_t size;
@@ -73,8 +71,8 @@
 {
 	PoolAlloc *alloc;
 
-	if (size > MAX_ALLOC_SIZE)
-		i_panic("Trying to allocate too much memory");
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
 	alloc = t_malloc0(sizeof(PoolAlloc) + size);
 	alloc->size.size = size;
@@ -99,6 +97,9 @@
 	PoolAlloc *alloc, *new_alloc;
         size_t old_size;
 	unsigned char *rmem;
+
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
 	if (mem == NULL)
 		return pool_data_stack_malloc(pool, size);

Index: mempool-system.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/mempool-system.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mempool-system.c	18 Dec 2002 15:15:41 -0000	1.5
+++ mempool-system.c	22 Dec 2002 07:06:16 -0000	1.6
@@ -30,8 +30,6 @@
 
 #include <stdlib.h>
 
-#define MAX_ALLOC_SIZE SSIZE_T_MAX
-
 typedef struct {
 	union {
 		size_t size;
@@ -75,8 +73,8 @@
 {
 	PoolAlloc *alloc;
 
-	if (size > MAX_ALLOC_SIZE)
-		i_panic("Trying to allocate too much memory");
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
 	alloc = calloc(sizeof(PoolAlloc) + size, 1);
 	if (alloc == NULL)
@@ -98,6 +96,9 @@
 	PoolAlloc *alloc;
 	size_t old_size;
 	char *rmem;
+
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
 	if (mem == NULL) {
 		alloc = NULL;

Index: str.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/str.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- str.c	22 Dec 2002 06:25:50 -0000	1.3
+++ str.c	22 Dec 2002 07:06:16 -0000	1.4
@@ -23,6 +23,7 @@
 
 #include "lib.h"
 #include "buffer.h"
+#include "printf-upper-bound.h"
 #include "str.h"
 
 #include <stdio.h>

Index: strfuncs.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/strfuncs.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- strfuncs.c	22 Dec 2002 06:25:50 -0000	1.21
+++ strfuncs.c	22 Dec 2002 07:06:16 -0000	1.22
@@ -1,32 +1,32 @@
 /*
- strfuncs.c : String manipulation functions (note: LGPL, because the )
+ strfuncs.c : String manipulation functions
 
-    Copyright (C) 2001-2002 Timo Sirainen
+    Copyright (c) 2002 Timo Sirainen
 
-    printf_string_upper_bound() code is taken from GLIB:
-    Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
-    Modified by the GLib Team and others 1997-1999.
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
 
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
 
-    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.
-  
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the
-    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-    Boston, MA 02111-1307, USA.
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
 
 /* @UNSAFE: whole file */
 
 #include "lib.h"
+#include "printf-upper-bound.h"
 #include "strfuncs.h"
 
 #include <stdio.h>
@@ -35,301 +35,6 @@
 
 #define STRCONCAT_BUFSIZE 512
 
-typedef void *(*ALLOC_FUNC)(Pool, size_t);
-
-static void *tp_malloc(Pool pool __attr_unused__, size_t size)
-{
-        return t_malloc(size);
-}
-
-typedef union  _GDoubleIEEE754  GDoubleIEEE754;
-#define G_IEEE754_DOUBLE_BIAS   (1023)
-/* multiply with base2 exponent to get base10 exponent (nomal numbers) */
-#define G_LOG_2_BASE_10         (0.30102999566398119521)
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-union _GDoubleIEEE754
-{
-  double v_double;
-  struct {
-    unsigned int mantissa_low : 32;
-    unsigned int mantissa_high : 20;
-    unsigned int biased_exponent : 11;
-    unsigned int sign : 1;
-  } mpn;
-};
-#elif G_BYTE_ORDER == G_BIG_ENDIAN
-union _GDoubleIEEE754
-{
-  double v_double;
-  struct {
-    unsigned int sign : 1;
-    unsigned int biased_exponent : 11;
-    unsigned int mantissa_high : 20;
-    unsigned int mantissa_low : 32;
-  } mpn;
-};
-#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
-#error unknown ENDIAN type
-#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
-
-typedef struct
-{
-  unsigned int min_width;
-  unsigned int precision;
-  int alternate_format, zero_padding, adjust_left, locale_grouping;
-  int add_space, add_sign, possible_sign, seen_precision;
-  int mod_long, mod_extra_long;
-} PrintfArgSpec;
-
-#if (SIZEOF_LONG > 4) || (SIZEOF_VOID_P > 4)
-#  define HONOUR_LONGS 1
-#else
-#  define HONOUR_LONGS 0
-#endif
-
-size_t printf_string_upper_bound(const char *format, va_list args)
-{
-  size_t len = 1;
-
-  if (!format)
-    return len;
-
-  while (*format)
-    {
-      register char c = *format++;
-
-      if (c != '%')
-        len += 1;
-      else /* (c == '%') */
-        {
-          PrintfArgSpec spec;
-          int seen_l = FALSE, conv_done = FALSE;
-          unsigned int conv_len = 0;
-
-          memset(&spec, 0, sizeof(spec));
-          do
-            {
-              c = *format++;
-              switch (c)
-                {
-                  GDoubleIEEE754 u_double;
-                  unsigned int v_uint;
-                  int v_int;
-                  const char *v_string;
-
-                  /* beware of positional parameters
-                   */
-                case '$':
-                  i_panic("unable to handle positional parameters (%%n$)");
-                  break;
-
-                  /* parse flags
-                   */
-                case '#':
-                  spec.alternate_format = TRUE;
-                  break;
-                case '0':
-                  spec.zero_padding = TRUE;
-                  break;
-                case '-':
-                  spec.adjust_left = TRUE;
-                  break;
-                case ' ':
-                  spec.add_space = TRUE;
-                  break;
-                case '+':
-                  spec.add_sign = TRUE;
-                  break;
-                case '\'':
-                  spec.locale_grouping = TRUE;
-                  break;
-
-                  /* parse output size specifications
-                   */
-                case '.':
-                  spec.seen_precision = TRUE;
-                  break;
-                case '1':
-                case '2':
-                case '3':
-                case '4':
-                case '5':
-                case '6':
-                case '7':
-                case '8':
-                case '9':
-                  v_uint = c - '0';
-                  c = *format;
-                  while (c >= '0' && c <= '9')
-                    {
-                      format++;
-                      v_uint = v_uint * 10 + (c - '0');
-                      c = *format;
-                    }
-                  if (spec.seen_precision)
-                    spec.precision = I_MAX (spec.precision, v_uint);
-                  else
-                    spec.min_width = I_MAX (spec.min_width, v_uint);
-                  break;
-                case '*':
-                  v_int = va_arg (args, int);
-                  if (spec.seen_precision)
-                    {
-                      /* forget about negative precision */
-                      if (v_int >= 0)
-                        spec.precision = I_MAX ((int)spec.precision, v_int);
-                    }
-                  else
-                    {
-                      if (v_int < 0)
-                        {
-                          v_int = - v_int;
-                          spec.adjust_left = TRUE;
-                        }
-                      spec.min_width = I_MAX ((int)spec.min_width, v_int);
-                    }
-                  break;
-
-                  /* parse type modifiers
-                   */
-                case 'h':
-		  /* ignore */
-                  break;
-                case 'l':
-                  if (!seen_l)
-                    {
-                      spec.mod_long = TRUE;
-                      seen_l = TRUE;
-                      break;
-                    }
-                  /* else, fall through */
-                case 'L':
-                  spec.mod_long = TRUE;
-                  spec.mod_extra_long = TRUE;
-                  break;
-
-                  /* parse output conversions
-                   */
-                case '%':
-                  conv_len += 1;
-                  break;
-                case 'o':
-                  conv_len += 2;
-                  /* fall through */
-                case 'd':
-                case 'i':
-                  conv_len += 1; /* sign */
-                  /* fall through */
-                case 'u':
-                  conv_len += 4;
-                  /* fall through */
-                case 'x':
-                case 'X':
-                  spec.possible_sign = TRUE;
-                  conv_len += 10;
-                  if (spec.mod_long && HONOUR_LONGS)
-                    conv_len *= 2;
-                  if (spec.mod_extra_long)
-                    conv_len *= 2;
-                  if (spec.mod_extra_long)
-                    {
-#if SIZEOF_LONG_LONG > 0
-                      (void) va_arg (args, long long);
-#else
-		      i_panic("mod_extra_long not supported");
-#endif
-                    }
-                  else if (spec.mod_long)
-                    (void) va_arg (args, long);
-                  else
-                    (void) va_arg (args, int);
-                  break;
-                case 'A':
-                case 'a':
-                  /*          0x */
-                  conv_len += 2;
-                  /* fall through */
-                case 'g':
-                case 'G':
-                case 'e':
-                case 'E':
-                case 'f':
-                  spec.possible_sign = TRUE;
-                  /*          n   .   dddddddddddddddddddddddd   E   +-  eeee */
-                  conv_len += 1 + 1 + I_MAX (24, spec.precision) + 1 + 1 + 4;
-                  if (spec.mod_extra_long)
-                    i_panic("unable to handle long double");
-#ifdef HAVE_LONG_DOUBLE
-#error need to implement special handling for long double
-#endif
-                  u_double.v_double = va_arg (args, double);
-                  /* %f can expand up to all significant digits before '.' (308) */
-                  if (c == 'f' &&
-                      u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047)
-                    {
-                      int exp = u_double.mpn.biased_exponent;
-
-                      exp -= G_IEEE754_DOUBLE_BIAS;
-                      exp = exp * G_LOG_2_BASE_10 + 1;
-                      conv_len += exp;
-                    }
-                  /* some printf() implementations require extra padding for rounding */
-                  conv_len += 2;
-                  /* we can't really handle locale specific grouping here */
-                  if (spec.locale_grouping)
-                    conv_len *= 2;
-                  break;
-                case 'c':
-                  conv_len += spec.mod_long ? MB_LEN_MAX : 1;
-                  (void) va_arg (args, int);
-                  break;
-                case 's':
-                  v_string = va_arg (args, char*);
-                  if (!v_string)
-                    conv_len += 8; /* hold "(null)" */
-                  else if (spec.seen_precision)
-                    conv_len += spec.precision;
-                  else
-                    conv_len += strlen (v_string);
-                  conv_done = TRUE;
-                  if (spec.mod_long)
-                    i_panic("unable to handle wide char strings");
-                  break;
-                case 'p':
-                  spec.alternate_format = TRUE;
-                  conv_len += 10;
-                  if (HONOUR_LONGS)
-                    conv_len *= 2;
-		  conv_done = TRUE;
-		  (void) va_arg (args, void*);
-                  break;
-
-                  /* handle invalid cases
-                   */
-                case '\000':
-                  /* no conversion specification, bad bad */
-		  i_panic("Missing conversion specifier");
-                  break;
-                default:
-                  i_panic("unable to handle `%c' while parsing format", c);
-                  break;
-                }
-              conv_done |= conv_len > 0;
-            }
-          while (!conv_done);
-          /* handle width specifications */
-          conv_len = I_MAX (conv_len, I_MAX (spec.precision, spec.min_width));
-          /* handle flags */
-          conv_len += spec.alternate_format ? 2 : 0;
-          conv_len += (spec.add_space || spec.add_sign || spec.possible_sign);
-          /* finally done */
-          len += conv_len;
-        } /* else (c == '%') */
-    } /* while (*format) */
-
-  return len;
-}
-
 static const char *fix_format_real(const char *fmt, const char *p)
 {
 	const char *errstr;
@@ -434,74 +139,29 @@
 	return ret;
 }
 
-#define STRDUP_CORE(alloc_func, str) STMT_START { \
-	void *mem;				\
-	size_t len;				\
-						\
-	for (len = 0; (str)[len] != '\0'; )	\
-		len++;				\
-	len++;					\
-	mem = alloc_func;			\
-	memcpy(mem, str, sizeof(str[0])*len);	\
-	return mem;				\
-	} STMT_END
-
 char *p_strdup(Pool pool, const char *str)
 {
-	if (str == NULL)
-                return NULL;
-
-        STRDUP_CORE(p_malloc(pool, len), str);
-}
-
-const char *t_strdup(const char *str)
-{
-	if (str == NULL)
-                return NULL;
-
-        STRDUP_CORE(t_malloc(len), str);
-}
+	void *mem;
+	size_t len;
 
-char *t_strdup_noconst(const char *str)
-{
 	if (str == NULL)
                 return NULL;
 
-        STRDUP_CORE(t_malloc(len), str);
-}
-
-int *p_intarrdup(Pool pool, const int *arr)
-{
-	if (arr == NULL)
-                return NULL;
-
-        STRDUP_CORE(p_malloc(pool, sizeof(int) * len), arr);
-}
-
-const int *t_intarrdup(const int *arr)
-{
-	if (arr == NULL)
-                return NULL;
+	for (len = 0; (str)[len] != '\0'; )
+		len++;
+	len++;
 
-        STRDUP_CORE(t_malloc(sizeof(int) * len), arr);
+	mem = p_malloc(pool, len);
+	memcpy(mem, str, len);
+	return mem;
 }
 
-#define STRDUP_EMPTY_CORE(alloc_func, str) STMT_START { \
-	if ((str) == NULL || (str)[0] == '\0')	\
-                return NULL;			\
-						\
-	STRDUP_CORE(alloc_func, str);		\
-	} STMT_END
-
-
 char *p_strdup_empty(Pool pool, const char *str)
 {
-        STRDUP_EMPTY_CORE(p_malloc(pool, len), str);
-}
+	if (str == NULL || *str == '\0')
+                return NULL;
 
-const char *t_strdup_empty(const char *str)
-{
-        STRDUP_EMPTY_CORE(t_malloc(len), str);
+	return p_strdup(pool, str);
 }
 
 char *p_strdup_until(Pool pool, const char *start, const char *end)
@@ -512,36 +172,18 @@
 	i_assert(start <= end);
 
 	size = (size_t) (end-start);
-	i_assert(size < SSIZE_T_MAX);
 
 	mem = p_malloc(pool, size + 1);
 	memcpy(mem, start, size);
 	return mem;
 }
 
-const char *t_strdup_until(const char *start, const char *end)
-{
-	size_t size;
-	char *mem;
-
-	i_assert(start <= end);
-
-	size = (size_t) (end-start);
-	i_assert(size < SSIZE_T_MAX);
-
-	mem = t_malloc(size + 1);
-	memcpy(mem, start, size);
-	mem[size] = '\0';
-	return mem;
-}
-
-static inline char *strndup_core(const char *str, size_t max_chars,
-				 ALLOC_FUNC alloc, Pool pool)
+char *p_strndup(Pool pool, const char *str, size_t max_chars)
 {
 	char *mem;
 	size_t len;
 
-	i_assert(max_chars < SSIZE_T_MAX);
+	i_assert(max_chars != (size_t)-1);
 
 	if (str == NULL)
 		return NULL;
@@ -550,22 +192,12 @@
 	while (str[len] != '\0' && len < max_chars)
 		len++;
 
-	mem = alloc(pool, len+1);
+	mem = pool->malloc(pool, len+1);
 	memcpy(mem, str, len);
 	mem[len] = '\0';
 	return mem;
 }
 
-char *p_strndup(Pool pool, const char *str, size_t max_chars)
-{
-        return strndup_core(str, max_chars, pool->malloc, pool);
-}
-
-const char *t_strndup(const char *str, size_t max_chars)
-{
-        return strndup_core(str, max_chars, tp_malloc, NULL);
-}
-
 char *p_strdup_printf(Pool pool, const char *format, ...)
 {
 	va_list args;
@@ -578,70 +210,32 @@
 	return ret;
 }
 
-const char *t_strdup_printf(const char *format, ...)
-{
-	va_list args;
-        const char *ret;
-
-	va_start(args, format);
-        ret = t_strdup_vprintf(format, args);
-	va_end(args);
-
-	return ret;
-}
-
-static inline char *
-strdup_vprintf_core(const char *format, va_list args,
-		    ALLOC_FUNC alloc_func, Pool pool)
+char *p_strdup_vprintf(Pool pool, const char *format, va_list args)
 {
-        va_list temp_args;
 	char *ret;
 	size_t len;
 
-	if (format == NULL)
-		return NULL;
+	i_assert(format != NULL);
 
-	format = printf_string_fix_format(format);
+	if (pool != data_stack_pool)
+		t_push();
 
-	VA_COPY(temp_args, args);
+	format = printf_string_fix_format(format);
 
 	len = printf_string_upper_bound(format, args);
-        ret = alloc_func(pool, len);
+        ret = p_malloc(pool, len);
 
 #ifdef HAVE_VSNPRINTF
 	vsnprintf(ret, len, format, args);
 #else
 	vsprintf(ret, format, args);
 #endif
-
-	va_end(temp_args);
-
-        return ret;
-}
-
-char *p_strdup_vprintf(Pool pool, const char *format, va_list args)
-{
-	char *ret;
-
-	t_push();
-	ret = strdup_vprintf_core(format, args, pool->malloc, pool);
-	t_pop();
+	if (pool != data_stack_pool)
+		t_pop();
 	return ret;
 }
 
-const char *t_strdup_vprintf(const char *format, va_list args)
-{
-        return strdup_vprintf_core(format, args, tp_malloc, NULL);
-}
-
-void p_strdup_replace(Pool pool, char **dest, const char *str)
-{
-	p_free(pool, *dest);
-        *dest = p_strdup(pool, str);
-}
-
-const char *temp_strconcat(const char *str1, va_list args,
-			   size_t *ret_len)
+const char *_vstrconcat(const char *str1, va_list args, size_t *ret_len)
 {
 	const char *str;
         char *temp;
@@ -688,7 +282,7 @@
 
 	va_start(args, str1);
 
-	temp = temp_strconcat(str1, args, &len);
+	temp = _vstrconcat(str1, args, &len);
 	if (temp == NULL)
 		ret = NULL;
 	else {
@@ -700,6 +294,48 @@
         return ret;
 }
 
+const char *t_strdup(const char *str)
+{
+	return p_strdup(data_stack_pool, str);
+}
+
+char *t_strdup_noconst(const char *str)
+{
+	return p_strdup(data_stack_pool, str);
+}
+
+const char *t_strdup_empty(const char *str)
+{
+	return p_strdup_empty(data_stack_pool, str);
+}
+
+const char *t_strdup_until(const char *start, const char *end)
+{
+	return p_strdup_until(data_stack_pool, start, end);
+}
+
+const char *t_strndup(const char *str, size_t max_chars)
+{
+	return p_strndup(data_stack_pool, str, max_chars);
+}
+
+const char *t_strdup_printf(const char *format, ...)
+{
+	va_list args;
+	const char *ret;
+
+	va_start(args, format);
+	ret = p_strdup_vprintf(data_stack_pool, format, args);
+	va_end(args);
+
+	return ret;
+}
+
+const char *t_strdup_vprintf(const char *format, va_list args)
+{
+	return p_strdup_vprintf(data_stack_pool, format, args);
+}
+
 const char *t_strconcat(const char *str1, ...)
 {
 	va_list args;
@@ -708,7 +344,7 @@
 
 	va_start(args, str1);
 
-	ret = temp_strconcat(str1, args, &len);
+	ret = _vstrconcat(str1, args, &len);
 	if (ret != NULL)
 		t_buffer_alloc(len);
 

Index: strfuncs.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/strfuncs.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- strfuncs.h	21 Dec 2002 22:02:58 -0000	1.11
+++ strfuncs.h	22 Dec 2002 07:06:16 -0000	1.12
@@ -6,7 +6,6 @@
 
 #define MAX_INT_STRLEN ((sizeof(uintmax_t) * CHAR_BIT + 2) / 3 + 1)
 
-size_t printf_string_upper_bound(const char *format, va_list args);
 const char *printf_string_fix_format(const char *fmt) __attr_format_arg__(1);
 
 /* Returns -1 if dest wasn't large enough, 0 if not. */
@@ -19,9 +18,6 @@
 char *p_strndup(Pool pool, const char *str, size_t max_chars);
 char *p_strdup_printf(Pool pool, const char *format, ...) __attr_format__(2, 3);
 char *p_strdup_vprintf(Pool pool, const char *format, va_list args);
-void p_strdup_replace(Pool pool, char **dest, const char *str);
-int *p_intarrdup(Pool pool, const int *arr);
-
 char *p_strconcat(Pool pool, const char *str1, ...); /* NULL terminated */
 
 /* same with temporary memory allocations: */
@@ -32,16 +28,16 @@
 const char *t_strndup(const char *str, size_t max_chars);
 const char *t_strdup_printf(const char *format, ...) __attr_format__(1, 2);
 const char *t_strdup_vprintf(const char *format, va_list args);
-const int *t_intarrdup(const int *arr);
-
 const char *t_strconcat(const char *str1, ...); /* NULL terminated */
+
+/* Like t_strdup(), but stop at cutchar. */
 const char *t_strcut(const char *str, char cutchar);
 
 /* Return TRUE if all characters in string are numbers.
    Stop when `end_char' is found from string. */
 int is_numeric(const char *str, char end_char);
 
-/* like strlcpy(), but return -1 if buffer was overflown, 0 if not. */
+/* Like strlcpy(), but return -1 if buffer was overflown, 0 if not. */
 int strocpy(char *dest, const char *src, size_t dstsize);
 
 /* Print given directory and file to dest buffer, separated with '/'.
@@ -66,6 +62,6 @@
 const char *dec2str(uintmax_t number);
 
 /* INTERNAL */
-const char *temp_strconcat(const char *str1, va_list args, size_t *ret_len);
+const char *_vstrconcat(const char *str1, va_list args, size_t *ret_len);
 
 #endif




More information about the dovecot-cvs mailing list