From 70d4a9343f4a06ae1344b6a1622fce7ed89743fc Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 2 Mar 2005 05:22:22 +0000 Subject: [PATCH] Prevent large allocation in snprintf to hold positional parameters. Allocated size based on format string. --- src/port/snprintf.c | 53 ++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/src/port/snprintf.c b/src/port/snprintf.c index f52e1f4fe1..cba8ad5b1c 100644 --- a/src/port/snprintf.c +++ b/src/port/snprintf.c @@ -32,18 +32,17 @@ * SUCH DAMAGE. */ -/* might be in either frontend or backend */ +#ifndef FRONTEND +#include "postgres.h" +#else #include "postgres_fe.h" +#endif #ifndef WIN32 #include #endif #include -#ifndef NL_ARGMAX -#define NL_ARGMAX 4096 -#endif - /* ** SNPRINTF, VSNPRINT -- counted versions of printf ** @@ -66,7 +65,7 @@ * causing nasty effects. **************************************************************/ -/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.11 2005/03/02 03:21:52 momjian Exp $";*/ +/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.12 2005/03/02 05:22:22 momjian Exp $";*/ int snprintf(char *str, size_t count, const char *fmt,...); int vsnprintf(char *str, size_t count, const char *fmt, va_list args); @@ -157,11 +156,9 @@ dopr(char *buffer, const char *format, va_list args, char *end) int realpos = 0; int position; char *output; - /* In thread mode this structure is too large. */ -#ifndef ENABLE_THREAD_SAFETY - static -#endif - struct{ + int percents = 1; + const char *p; + struct fmtpar { const char* fmtbegin; const char* fmtend; void* value; @@ -179,10 +176,30 @@ dopr(char *buffer, const char *format, va_list args, char *end) int pointflag; char func; int realpos; - } fmtpar[NL_ARGMAX+1], *fmtparptr[NL_ARGMAX+1]; - + } *fmtpar, **fmtparptr; + /* Create enough structures to hold all arguments */ + for (p = format; *p != '\0'; p++) + if (*p == '%') /* counts %% as two, so overcounts */ + percents++; +#ifndef FRONTEND + fmtpar = pgport_palloc(sizeof(struct fmtpar) * percents); + fmtparptr = pgport_palloc(sizeof(struct fmtpar *) * percents); +#else + if ((fmtpar = malloc(sizeof(struct fmtpar) * percents)) == NULL) + { + fprintf(stderr, _("out of memory\n")); + exit(1); + } + if ((fmtparptr = malloc(sizeof(struct fmtpar *) * percents)) == NULL) + { + fprintf(stderr, _("out of memory\n")); + exit(1); + } +#endif + format_save = format; + output = buffer; while ((ch = *format++)) { @@ -418,9 +435,7 @@ dopr(char *buffer, const char *format, va_list args, char *end) performpr: /* shuffle pointers */ for(i = 1; i < fmtpos; i++) - { fmtparptr[i] = &fmtpar[fmtpar[i].realpos]; - } output = buffer; format = format_save; while ((ch = *format++)) @@ -465,6 +480,14 @@ nochar: ; /* semicolon required because a goto has to be attached to a statement */ } *output = '\0'; + +#ifndef FRONTEND + pgport_pfree(fmtpar); + pgport_pfree(fmtparptr); +#else + free(fmtpar); + free(fmtparptr); +#endif } static void