/ Check-in [b0fb4a3c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a potential buffer overrun in the replace() function. (CVS 3947)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b0fb4a3cf6ddbc17ccd0c719b34a720d9090bc93
User & Date: danielk1977 2007-05-08 14:39:04
Context
2007-05-08
14:51
Add the max_page_count pragma used to limit the maximum size of a database file. Untested. (CVS 3948) check-in: b1b74f06 user: drh tags: trunk
14:39
Fix a potential buffer overrun in the replace() function. (CVS 3947) check-in: b0fb4a3c user: danielk1977 tags: trunk
13:58
Add more code to enforce the limits specified in limits.h. (CVS 3946) check-in: c59d4360 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/func.c.

    12     12   ** This file contains the C functions that implement various SQL
    13     13   ** functions of SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: func.c,v 1.147 2007/05/08 12:12:17 drh Exp $
           19  +** $Id: func.c,v 1.148 2007/05/08 14:39:04 danielk1977 Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   #include <ctype.h>
    23     23   /* #include <math.h> */
    24     24   #include <stdlib.h>
    25     25   #include <assert.h>
    26     26   #include "vdbeInt.h"
................................................................................
   749    749     if( zPattern==0 || zPattern[0]==0 ) return;
   750    750     nRep = sqlite3_value_bytes(argv[2]);
   751    751     zRep = sqlite3_value_text(argv[2]);
   752    752     if( zRep==0 ) return;
   753    753     if( nPattern>=nRep ){
   754    754       nOut = nStr;
   755    755     }else{
   756         -    nOut = (nStr/nPattern + 1)*nRep;
          756  +    i64 nOut64 = (i64)(nStr/nPattern + 1) * (i64)nRep;
          757  +    nOut = ((nOut64>SQLITE_MAX_LENGTH) ? SQLITE_MAX_LENGTH : nOut64);
   757    758     }
   758    759     zOut = sqlite3_malloc(nOut+1);
   759    760     if( zOut==0 ) return;
   760    761     loopLimit = nStr - nPattern;  
   761    762     for(i=j=0; i<=loopLimit; i++){
   762    763       if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
   763    764         zOut[j++] = zStr[i];
   764    765       }else{
          766  +      if( (j+nRep+loopLimit-i)>SQLITE_MAX_LENGTH ){
          767  +        sqlite3_result_error(context, "replace() is too large", -1);
          768  +        sqlite3_free(zOut);
          769  +        return;
          770  +      }
   765    771         memcpy(&zOut[j], zRep, nRep);
   766    772         j += nRep;
   767    773         i += nPattern-1;
   768    774       }
   769    775     }
   770    776     memcpy(&zOut[j], &zStr[i], nStr-i);
   771    777     j += nStr - i;

Changes to test/func.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing built-in functions.
    13     13   #
    14         -# $Id: func.test,v 1.64 2007/05/07 16:58:02 danielk1977 Exp $
           14  +# $Id: func.test,v 1.65 2007/05/08 14:39:04 danielk1977 Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a table to work with.
    20     20   #
    21     21   do_test func-0.0 {
................................................................................
   329    329   } {00112233445566778899AABBCCDDEEFF}
   330    330   do_test func-9.11 {
   331    331     execsql {SELECT hex(replace('abcdefg','ef','12'))}
   332    332   } {61626364313267}
   333    333   do_test func-9.12 {
   334    334     execsql {SELECT hex(replace('abcdefg','','12'))}
   335    335   } {{}}
          336  +breakpoint
   336    337   do_test func-9.13 {
   337    338     execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
   338    339   } {616161616161626364656667}
   339    340   
   340    341   # Use the "sqlite_register_test_function" TCL command which is part of
   341    342   # the text fixture in order to verify correct operation of some of
   342    343   # the user-defined SQL function APIs that are not used by the built-in
................................................................................
   778    779   } {{This is the larger-main test string}}
   779    780   do_test func-21.8 {
   780    781     execsql {
   781    782       SELECT replace("aaaaaaa", "a", "0123456789");
   782    783     }
   783    784   } {0123456789012345678901234567890123456789012345678901234567890123456789}
   784    785   
          786  +do_test func-21.9 {
          787  +  # Attempt to exploit a buffer-overflow that at one time existed 
          788  +  # in the REPLACE function. 
          789  +  set ::str "[string repeat A 29998]CC[string repeat A 35537]"
          790  +  set ::rep [string repeat B 65536]
          791  +  execsql {
          792  +    SELECT LENGTH(REPLACE($::str, 'C', $::rep));
          793  +  }
          794  +} [expr 29998 + 2*65536 + 35537]
          795  +
   785    796   # Tests for the TRIM, LTRIM and RTRIM functions.
   786    797   #
   787    798   do_test func-22.1 {
   788    799     catchsql {SELECT trim(1,2,3)}
   789    800   } {1 {wrong number of arguments to function trim()}}
   790    801   do_test func-22.2 {
   791    802     catchsql {SELECT ltrim(1,2,3)}