diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 9066776862f..a4f420042c0 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * formatting.c * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.69.2.1 2005/03/26 00:42:21 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.69.2.2 2007/06/29 01:52:14 tgl Exp $ * * * Portions Copyright (c) 1999-2003, PostgreSQL Global Development Group @@ -74,6 +74,7 @@ #include #include #include +#include #include "utils/builtins.h" #include "utils/date.h" @@ -108,8 +109,8 @@ * More is in float.c * ---------- */ -#define MAXFLOATWIDTH 64 -#define MAXDOUBLEWIDTH 128 +#define MAXFLOATWIDTH 60 +#define MAXDOUBLEWIDTH 500 /* ---------- * External (defined in PgSQL dt.c (timestamp utils)) @@ -1448,7 +1449,7 @@ str_numth(char *dest, char *num, int type) } /* ---------- - * Convert string to upper-string. Input string is modified in place. + * Convert string to upper case. Input string is modified in place. * ---------- */ static char * @@ -1468,7 +1469,7 @@ str_toupper(char *buff) } /* ---------- - * Convert string to lower-string. Input string is modified in place. + * Convert string to lower case. Input string is modified in place. * ---------- */ static char * @@ -1996,19 +1997,16 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node, void *data) case DCH_TZ: if (flag == TO_CHAR && tmtcTzn(tmtc)) { - int siz = strlen(tmtcTzn(tmtc)); - if (arg == DCH_TZ) strcpy(inout, tmtcTzn(tmtc)); else { - char *p = palloc(siz); + char *p = pstrdup(tmtcTzn(tmtc)); - strcpy(p, tmtcTzn(tmtc)); strcpy(inout, str_tolower(p)); pfree(p); } - return siz - 1; + return strlen(inout) - 1; } else if (flag == FROM_CHAR) ereport(ERROR, @@ -3221,7 +3219,7 @@ static char * fill_str(char *str, int c, int max) { memset(str, c, max); - *(str + max + 1) = '\0'; + *(str + max) = '\0'; return str; } @@ -4333,10 +4331,9 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, #define NUM_TOCHAR_prepare \ do { \ len = VARSIZE(fmt) - VARHDRSZ; \ - if (len <= 0) \ + if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ) \ return DirectFunctionCall1(textin, CStringGetDatum("")); \ - result = (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \ - memset(result, 0, (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ ); \ + result = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \ format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree); \ } while (0) @@ -4348,28 +4345,18 @@ do { \ do { \ NUM_processor(format, &Num, VARDATA(result), \ numstr, plen, sign, TO_CHAR); \ - pfree(orgnum); \ \ - if (shouldFree) \ - pfree(format); \ + if (shouldFree) \ + pfree(format); \ \ - /* - * for result is allocated max memory, which current format-picture\ - * needs, now it must be re-allocate to result real size \ + /* \ + * Convert null-terminated representation of result to standard text. \ + * The result is usually much bigger than it needs to be, but there \ + * seems little point in realloc'ing it smaller. \ */ \ - if (!(len = strlen(VARDATA(result)))) \ - { \ - pfree(result); \ - PG_RETURN_NULL(); \ - } \ - \ - result_tmp = result; \ - result = (text *) palloc( len + 1 + VARHDRSZ); \ - \ - strcpy( VARDATA(result), VARDATA(result_tmp)); \ - VARATT_SIZEP(result) = len + VARHDRSZ; \ - pfree(result_tmp); \ -} while(0) + len = strlen(VARDATA(result)); \ + VARATT_SIZEP(result) = len + VARHDRSZ; \ +} while (0) /* ------------------- * NUMERIC to_number() (convert string to numeric) @@ -4391,7 +4378,7 @@ numeric_to_number(PG_FUNCTION_ARGS) len = VARSIZE(fmt) - VARHDRSZ; - if (len <= 0) + if (len <= 0 || len >= INT_MAX/NUM_MAX_ITEM_SIZ) PG_RETURN_NULL(); format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree); @@ -4426,8 +4413,7 @@ numeric_to_char(PG_FUNCTION_ARGS) text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; - text *result, - *result_tmp; + text *result; bool shouldFree; int len = 0, plen = 0, @@ -4450,7 +4436,6 @@ numeric_to_char(PG_FUNCTION_ARGS) numstr = orgnum = int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4, NumericGetDatum(x)))); - pfree(x); } else { @@ -4469,9 +4454,6 @@ numeric_to_char(PG_FUNCTION_ARGS) val = DatumGetNumeric(DirectFunctionCall2(numeric_mul, NumericGetDatum(value), NumericGetDatum(x))); - pfree(x); - pfree(a); - pfree(b); Num.pre += Num.multi; } @@ -4480,10 +4462,9 @@ numeric_to_char(PG_FUNCTION_ARGS) Int32GetDatum(Num.post))); orgnum = DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(x))); - pfree(x); if (*orgnum == '-') - { /* < 0 */ + { sign = '-'; numstr = orgnum + 1; } @@ -4502,13 +4483,10 @@ numeric_to_char(PG_FUNCTION_ARGS) else if (len > Num.pre) { - fill_str(numstr, '#', Num.pre); + numstr = (char *) palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); *(numstr + Num.pre) = '.'; - fill_str(numstr + 1 + Num.pre, '#', Num.post); } - - if (IS_MULTI(&Num)) - pfree(val); } NUM_TOCHAR_finish; @@ -4526,8 +4504,7 @@ int4_to_char(PG_FUNCTION_ARGS) text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; - text *result, - *result_tmp; + text *result; bool shouldFree; int len = 0, plen = 0, @@ -4555,40 +4532,34 @@ int4_to_char(PG_FUNCTION_ARGS) orgnum = DatumGetCString(DirectFunctionCall1(int4out, Int32GetDatum(value))); } - len = strlen(orgnum); if (*orgnum == '-') - { /* < 0 */ + { sign = '-'; - --len; + orgnum++; } else sign = '+'; + len = strlen(orgnum); if (Num.post) { - int i; - numstr = (char *) palloc(len + Num.post + 2); - strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0)); + strcpy(numstr, orgnum); *(numstr + len) = '.'; - - for (i = len + 1; i <= len + Num.post; i++) - *(numstr + i) = '0'; + memset(numstr + len + 1, '0', Num.post); *(numstr + len + Num.post + 1) = '\0'; - pfree(orgnum); - orgnum = numstr; } else - numstr = orgnum + (*orgnum == '-' ? 1 : 0); + numstr = orgnum; if (Num.pre > len) plen = Num.pre - len; else if (len > Num.pre) { - fill_str(numstr, '#', Num.pre); + numstr = (char *) palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); *(numstr + Num.pre) = '.'; - fill_str(numstr + 1 + Num.pre, '#', Num.post); } } @@ -4607,8 +4578,7 @@ int8_to_char(PG_FUNCTION_ARGS) text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; - text *result, - *result_tmp; + text *result; bool shouldFree; int len = 0, plen = 0, @@ -4642,40 +4612,34 @@ int8_to_char(PG_FUNCTION_ARGS) orgnum = DatumGetCString(DirectFunctionCall1(int8out, Int64GetDatum(value))); - len = strlen(orgnum); if (*orgnum == '-') - { /* < 0 */ + { sign = '-'; - --len; + orgnum++; } else sign = '+'; + len = strlen(orgnum); if (Num.post) { - int i; - numstr = (char *) palloc(len + Num.post + 2); - strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0)); + strcpy(numstr, orgnum); *(numstr + len) = '.'; - - for (i = len + 1; i <= len + Num.post; i++) - *(numstr + i) = '0'; + memset(numstr + len + 1, '0', Num.post); *(numstr + len + Num.post + 1) = '\0'; - pfree(orgnum); - orgnum = numstr; } else - numstr = orgnum + (*orgnum == '-' ? 1 : 0); + numstr = orgnum; if (Num.pre > len) plen = Num.pre - len; else if (len > Num.pre) { - fill_str(numstr, '#', Num.pre); + numstr = (char *) palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); *(numstr + Num.pre) = '.'; - fill_str(numstr + 1 + Num.pre, '#', Num.post); } } @@ -4694,8 +4658,7 @@ float4_to_char(PG_FUNCTION_ARGS) text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; - text *result, - *result_tmp; + text *result; bool shouldFree; int len = 0, plen = 0, @@ -4754,9 +4717,9 @@ float4_to_char(PG_FUNCTION_ARGS) else if (len > Num.pre) { - fill_str(numstr, '#', Num.pre); + numstr = (char *) palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); *(numstr + Num.pre) = '.'; - fill_str(numstr + 1 + Num.pre, '#', Num.post); } } @@ -4775,8 +4738,7 @@ float8_to_char(PG_FUNCTION_ARGS) text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; - text *result, - *result_tmp; + text *result; bool shouldFree; int len = 0, plen = 0, @@ -4833,9 +4795,9 @@ float8_to_char(PG_FUNCTION_ARGS) else if (len > Num.pre) { - fill_str(numstr, '#', Num.pre); + numstr = (char *) palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); *(numstr + Num.pre) = '.'; - fill_str(numstr + 1 + Num.pre, '#', Num.post); } }