OSDN Git Service

Prevent buffer overrun while parsing an integer in a "query_int" value.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 27 Jan 2011 22:41:46 +0000 (17:41 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 27 Jan 2011 22:43:07 +0000 (17:43 -0500)
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

contrib/intarray/_int_bool.c

index 9390106..7a478fa 100644 (file)
@@ -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;