aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-01-27 17:41:46 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-01-27 17:43:07 -0500
commitd6d145673f8df3bd05939b1781e99acead9daae5 (patch)
tree99439793cb2c5cfd188ef2a9758d068d2e2b887c
parent67dbe720f6ba18393cd85574718aa2683b77a212 (diff)
downloadpostgresql-d6d145673f8df3bd05939b1781e99acead9daae5.tar.gz
postgresql-d6d145673f8df3bd05939b1781e99acead9daae5.zip
Prevent buffer overrun while parsing an integer in a "query_int" value.
contrib/intarray's gettoken() uses a fixed-size buffer to collect an integer's digits, and did not guard against overrunning the buffer. This is at least a backend crash risk, and in principle might allow arbitrary code execution. The code didn't check for overflow of the integer value either, which while not presenting a crash risk was still bad. Thanks to Apple Inc's security team for reporting this issue and supplying the fix. Security: CVE-2010-4015
-rw-r--r--contrib/intarray/_int_bool.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 93901066116..7a478faa83b 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -62,24 +62,25 @@ typedef struct
static int4
gettoken(WORKSTATE *state, int4 *val)
{
- char nnn[16],
- *curnnn;
+ char nnn[16];
+ int innn;
*val = 0; /* default result */
- curnnn = nnn;
+ innn = 0;
while (1)
{
+ if (innn >= sizeof(nnn))
+ return ERR; /* buffer overrun => syntax error */
switch (state->state)
{
case WAITOPERAND:
- curnnn = nnn;
+ innn = 0;
if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
*(state->buf) == '-')
{
state->state = WAITENDOPERAND;
- *curnnn = *(state->buf);
- curnnn++;
+ nnn[innn++] = *(state->buf);
}
else if (*(state->buf) == '!')
{
@@ -99,13 +100,18 @@ gettoken(WORKSTATE *state, int4 *val)
case WAITENDOPERAND:
if (*(state->buf) >= '0' && *(state->buf) <= '9')
{
- *curnnn = *(state->buf);
- curnnn++;
+ nnn[innn++] = *(state->buf);
}
else
{
- *curnnn = '\0';
- *val = (int4) atoi(nnn);
+ long lval;
+
+ nnn[innn] = '\0';
+ errno = 0;
+ lval = strtol(nnn, NULL, 0);
+ *val = (int4) lval;
+ if (errno != 0 || (long) *val != lval)
+ return ERR;
state->state = WAITOPERATOR;
return (state->count && *(state->buf) == '\0')
? ERR : VAL;