[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