Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 70d4a93

Browse files
committed
Prevent large allocation in snprintf to hold positional parameters.
Allocated size based on format string.
1 parent 3104a92 commit 70d4a93

File tree

1 file changed

+38
-15
lines changed

1 file changed

+38
-15
lines changed

src/port/snprintf.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,17 @@
3232
* SUCH DAMAGE.
3333
*/
3434

35-
/* might be in either frontend or backend */
35+
#ifndef FRONTEND
36+
#include "postgres.h"
37+
#else
3638
#include "postgres_fe.h"
39+
#endif
3740

3841
#ifndef WIN32
3942
#include <sys/ioctl.h>
4043
#endif
4144
#include <sys/param.h>
4245

43-
#ifndef NL_ARGMAX
44-
#define NL_ARGMAX 4096
45-
#endif
46-
4746
/*
4847
** SNPRINTF, VSNPRINT -- counted versions of printf
4948
**
@@ -66,7 +65,7 @@
6665
* causing nasty effects.
6766
**************************************************************/
6867

69-
/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.11 2005/03/02 03:21:52 momjian Exp $";*/
68+
/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.12 2005/03/02 05:22:22 momjian Exp $";*/
7069

7170
int snprintf(char *str, size_t count, const char *fmt,...);
7271
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)
157156
int realpos = 0;
158157
int position;
159158
char *output;
160-
/* In thread mode this structure is too large. */
161-
#ifndef ENABLE_THREAD_SAFETY
162-
static
163-
#endif
164-
struct{
159+
int percents = 1;
160+
const char *p;
161+
struct fmtpar {
165162
const char* fmtbegin;
166163
const char* fmtend;
167164
void* value;
@@ -179,10 +176,30 @@ dopr(char *buffer, const char *format, va_list args, char *end)
179176
int pointflag;
180177
char func;
181178
int realpos;
182-
} fmtpar[NL_ARGMAX+1], *fmtparptr[NL_ARGMAX+1];
183-
179+
} *fmtpar, **fmtparptr;
184180

181+
/* Create enough structures to hold all arguments */
182+
for (p = format; *p != '\0'; p++)
183+
if (*p == '%') /* counts %% as two, so overcounts */
184+
percents++;
185+
#ifndef FRONTEND
186+
fmtpar = pgport_palloc(sizeof(struct fmtpar) * percents);
187+
fmtparptr = pgport_palloc(sizeof(struct fmtpar *) * percents);
188+
#else
189+
if ((fmtpar = malloc(sizeof(struct fmtpar) * percents)) == NULL)
190+
{
191+
fprintf(stderr, _("out of memory\n"));
192+
exit(1);
193+
}
194+
if ((fmtparptr = malloc(sizeof(struct fmtpar *) * percents)) == NULL)
195+
{
196+
fprintf(stderr, _("out of memory\n"));
197+
exit(1);
198+
}
199+
#endif
200+
185201
format_save = format;
202+
186203
output = buffer;
187204
while ((ch = *format++))
188205
{
@@ -418,9 +435,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
418435
performpr:
419436
/* shuffle pointers */
420437
for(i = 1; i < fmtpos; i++)
421-
{
422438
fmtparptr[i] = &fmtpar[fmtpar[i].realpos];
423-
}
424439
output = buffer;
425440
format = format_save;
426441
while ((ch = *format++))
@@ -465,6 +480,14 @@ dopr(char *buffer, const char *format, va_list args, char *end)
465480
; /* semicolon required because a goto has to be attached to a statement */
466481
}
467482
*output = '\0';
483+
484+
#ifndef FRONTEND
485+
pgport_pfree(fmtpar);
486+
pgport_pfree(fmtparptr);
487+
#else
488+
free(fmtpar);
489+
free(fmtparptr);
490+
#endif
468491
}
469492

470493
static void

0 commit comments

Comments
 (0)