/ 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 Unified Diffs Show Whitespace Changes Patch

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
764





765
766
767
768
769
770
771
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.147 2007/05/08 12:12:17 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/* #include <math.h> */
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
................................................................................
  if( zPattern==0 || zPattern[0]==0 ) return;
  nRep = sqlite3_value_bytes(argv[2]);
  zRep = sqlite3_value_text(argv[2]);
  if( zRep==0 ) return;
  if( nPattern>=nRep ){
    nOut = nStr;
  }else{
    nOut = (nStr/nPattern + 1)*nRep;

  }
  zOut = sqlite3_malloc(nOut+1);
  if( zOut==0 ) return;
  loopLimit = nStr - nPattern;  
  for(i=j=0; i<=loopLimit; i++){
    if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
      zOut[j++] = zStr[i];
    }else{





      memcpy(&zOut[j], zRep, nRep);
      j += nRep;
      i += nPattern-1;
    }
  }
  memcpy(&zOut[j], &zStr[i], nStr-i);
  j += nStr - i;







|







 







|
>








>
>
>
>
>







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

Changes to test/func.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
329
330
331
332
333
334
335

336
337
338
339
340
341
342
...
778
779
780
781
782
783
784










785
786
787
788
789
790
791
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.64 2007/05/07 16:58:02 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
} {00112233445566778899AABBCCDDEEFF}
do_test func-9.11 {
  execsql {SELECT hex(replace('abcdefg','ef','12'))}
} {61626364313267}
do_test func-9.12 {
  execsql {SELECT hex(replace('abcdefg','','12'))}
} {{}}

do_test func-9.13 {
  execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
} {616161616161626364656667}

# Use the "sqlite_register_test_function" TCL command which is part of
# the text fixture in order to verify correct operation of some of
# the user-defined SQL function APIs that are not used by the built-in
................................................................................
} {{This is the larger-main test string}}
do_test func-21.8 {
  execsql {
    SELECT replace("aaaaaaa", "a", "0123456789");
  }
} {0123456789012345678901234567890123456789012345678901234567890123456789}











# Tests for the TRIM, LTRIM and RTRIM functions.
#
do_test func-22.1 {
  catchsql {SELECT trim(1,2,3)}
} {1 {wrong number of arguments to function trim()}}
do_test func-22.2 {
  catchsql {SELECT ltrim(1,2,3)}







|







 







>







 







>
>
>
>
>
>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.65 2007/05/08 14:39:04 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
} {00112233445566778899AABBCCDDEEFF}
do_test func-9.11 {
  execsql {SELECT hex(replace('abcdefg','ef','12'))}
} {61626364313267}
do_test func-9.12 {
  execsql {SELECT hex(replace('abcdefg','','12'))}
} {{}}
breakpoint
do_test func-9.13 {
  execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
} {616161616161626364656667}

# Use the "sqlite_register_test_function" TCL command which is part of
# the text fixture in order to verify correct operation of some of
# the user-defined SQL function APIs that are not used by the built-in
................................................................................
} {{This is the larger-main test string}}
do_test func-21.8 {
  execsql {
    SELECT replace("aaaaaaa", "a", "0123456789");
  }
} {0123456789012345678901234567890123456789012345678901234567890123456789}

do_test func-21.9 {
  # Attempt to exploit a buffer-overflow that at one time existed 
  # in the REPLACE function. 
  set ::str "[string repeat A 29998]CC[string repeat A 35537]"
  set ::rep [string repeat B 65536]
  execsql {
    SELECT LENGTH(REPLACE($::str, 'C', $::rep));
  }
} [expr 29998 + 2*65536 + 35537]

# Tests for the TRIM, LTRIM and RTRIM functions.
#
do_test func-22.1 {
  catchsql {SELECT trim(1,2,3)}
} {1 {wrong number of arguments to function trim()}}
do_test func-22.2 {
  catchsql {SELECT ltrim(1,2,3)}