diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-01-27 17:41:46 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-01-27 17:43:07 -0500 |
commit | d6d145673f8df3bd05939b1781e99acead9daae5 (patch) | |
tree | 99439793cb2c5cfd188ef2a9758d068d2e2b887c | |
parent | 67dbe720f6ba18393cd85574718aa2683b77a212 (diff) | |
download | postgresql-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.c | 26 |
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; |