Prevent buffer overrun while parsing an integer in a "query_int" value.
authorTom Lane <[email protected]>
Thu, 27 Jan 2011 22:41:41 +0000 (17:41 -0500)
committerTom Lane <[email protected]>
Thu, 27 Jan 2011 22:42:39 +0000 (17:42 -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 3492100c0c2f9590f403660c86aedbfc17d686f9..072e8cc89773b052be3f0a805067db7ab3b0c8bc 100644 (file)
@@ -56,24 +56,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) == '!')
                {
@@ -93,13 +94,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;