Prevent buffer overrun while parsing an integer in a "query_int" value.
authorTom Lane <[email protected]>
Thu, 27 Jan 2011 22:42:00 +0000 (17:42 -0500)
committerTom Lane <[email protected]>
Thu, 27 Jan 2011 22:43:45 +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 64c8e00e2f3a5f9028a78c329c6024e35d38fe55..209c4d98bebefe6c51337a06076e4c5bad99c33f 100644 (file)
@@ -55,24 +55,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) == '!')
                {
@@ -92,13 +93,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;