Commit 7ccb6dc2 authored by Tom Lane's avatar Tom Lane

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
parent 0ac8c8df
...@@ -56,24 +56,25 @@ typedef struct ...@@ -56,24 +56,25 @@ typedef struct
static int4 static int4
gettoken(WORKSTATE *state, int4 *val) gettoken(WORKSTATE *state, int4 *val)
{ {
char nnn[16], char nnn[16];
*curnnn; int innn;
*val = 0; /* default result */ *val = 0; /* default result */
curnnn = nnn; innn = 0;
while (1) while (1)
{ {
if (innn >= sizeof(nnn))
return ERR; /* buffer overrun => syntax error */
switch (state->state) switch (state->state)
{ {
case WAITOPERAND: case WAITOPERAND:
curnnn = nnn; innn = 0;
if ((*(state->buf) >= '0' && *(state->buf) <= '9') || if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
*(state->buf) == '-') *(state->buf) == '-')
{ {
state->state = WAITENDOPERAND; state->state = WAITENDOPERAND;
*curnnn = *(state->buf); nnn[innn++] = *(state->buf);
curnnn++;
} }
else if (*(state->buf) == '!') else if (*(state->buf) == '!')
{ {
...@@ -93,13 +94,18 @@ gettoken(WORKSTATE *state, int4 *val) ...@@ -93,13 +94,18 @@ gettoken(WORKSTATE *state, int4 *val)
case WAITENDOPERAND: case WAITENDOPERAND:
if (*(state->buf) >= '0' && *(state->buf) <= '9') if (*(state->buf) >= '0' && *(state->buf) <= '9')
{ {
*curnnn = *(state->buf); nnn[innn++] = *(state->buf);
curnnn++;
} }
else else
{ {
*curnnn = '\0'; long lval;
*val = (int4) atoi(nnn);
nnn[innn] = '\0';
errno = 0;
lval = strtol(nnn, NULL, 0);
*val = (int4) lval;
if (errno != 0 || (long) *val != lval)
return ERR;
state->state = WAITOPERATOR; state->state = WAITOPERATOR;
return (state->count && *(state->buf) == '\0') return (state->count && *(state->buf) == '\0')
? ERR : VAL; ? ERR : VAL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment