Mercurial > dovecot > core-2.2
changeset 839:34cb1d196d2b HEAD
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.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 22 Dec 2002 09:06:16 +0200 |
parents | a6cd073c5283 |
children | 481a678ba019 |
files | COPYING src/lib/Makefile.am src/lib/data-stack.c src/lib/failures.c src/lib/imem.c src/lib/imem.h src/lib/mempool-alloconly.c src/lib/mempool-datastack.c src/lib/mempool-system.c src/lib/printf-upper-bound.c src/lib/printf-upper-bound.h src/lib/str.c src/lib/strfuncs.c src/lib/strfuncs.h src/master/settings.c |
diffstat | 15 files changed, 445 insertions(+), 485 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYING Sun Dec 22 08:28:44 2002 +0200 +++ b/COPYING Sun Dec 22 09:06:16 2002 +0200 @@ -6,4 +6,4 @@ src/lib/ - md5.c : Public Domain - base64.c, mkgmtime.c : BSD-like (read it) - - hash.c, primes.c, strfuncs.c, tree.c : LGPL v2 + - hash.c, primes.c, printf-upper-bound.c, tree.c : LGPL v2
--- a/src/lib/Makefile.am Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/Makefile.am Sun Dec 22 09:06:16 2002 +0200 @@ -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 \
--- a/src/lib/data-stack.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/data-stack.c Sun Dec 22 09:06:16 2002 +0200 @@ -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 @@ -278,6 +275,9 @@ { 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]; /* see if we're trying to grow the memory we allocated last */
--- a/src/lib/failures.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/failures.c Sun Dec 22 09:06:16 2002 +0200 @@ -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>
--- a/src/lib/imem.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/imem.c Sun Dec 22 09:06:16 2002 +0200 @@ -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;
--- a/src/lib/imem.h Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/imem.h Sun Dec 22 09:06:16 2002 +0200 @@ -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 */
--- a/src/lib/mempool-alloconly.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/mempool-alloconly.c Sun Dec 22 09:06:16 2002 +0200 @@ -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) { @@ -222,6 +225,9 @@ 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; old_size = 0;
--- a/src/lib/mempool-datastack.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/mempool-datastack.c Sun Dec 22 09:06:16 2002 +0200 @@ -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; @@ -100,6 +98,9 @@ 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);
--- a/src/lib/mempool-system.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/mempool-system.c Sun Dec 22 09:06:16 2002 +0200 @@ -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) @@ -99,6 +97,9 @@ 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; old_size = 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/printf-upper-bound.c Sun Dec 22 09:06:16 2002 +0200 @@ -0,0 +1,310 @@ +/* + 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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/printf-upper-bound.h Sun Dec 22 09:06:16 2002 +0200 @@ -0,0 +1,8 @@ +#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
--- a/src/lib/str.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/str.c Sun Dec 22 09:06:16 2002 +0200 @@ -23,6 +23,7 @@ #include "lib.h" #include "buffer.h" +#include "printf-upper-bound.h" #include "str.h" #include <stdio.h>
--- a/src/lib/strfuncs.c Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/strfuncs.c Sun Dec 22 09:06:16 2002 +0200 @@ -1,32 +1,32 @@ /* - strfuncs.c : String manipulation functions (note: LGPL, because the ) - - Copyright (C) 2001-2002 Timo Sirainen + strfuncs.c : String manipulation functions - 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. - + Copyright (c) 2002 Timo Sirainen - 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. + 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. + + 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); -} + void *mem; + size_t len; -const char *t_strdup(const char *str) -{ - if (str == NULL) - return NULL; - - STRDUP_CORE(t_malloc(len), str); -} - -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); -} + for (len = 0; (str)[len] != '\0'; ) + len++; + len++; -const int *t_intarrdup(const int *arr) -{ - if (arr == NULL) - return NULL; - - 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, ...) +char *p_strdup_vprintf(Pool pool, const char *format, va_list args) { - 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) -{ - va_list temp_args; char *ret; size_t len; - if (format == NULL) - return NULL; + i_assert(format != NULL); + + if (pool != data_stack_pool) + t_push(); format = printf_string_fix_format(format); - VA_COPY(temp_args, args); - 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);
--- a/src/lib/strfuncs.h Sun Dec 22 08:28:44 2002 +0200 +++ b/src/lib/strfuncs.h Sun Dec 22 09:06:16 2002 +0200 @@ -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 */ -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