SQLite

Check-in [0cf518ceeb]
Login

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

Overview
Comment:Do not allocate so much surplus memory in the implementation of the replace() function. (CVS 3951)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0cf518ceebda8e7421d054813f97cc447d292344
User & Date: drh 2007-05-08 15:46:18.000
Context
2007-05-08
15:59
Add new test file sqllimits1.test. (CVS 3952) (check-in: c897460397 user: danielk1977 tags: trunk)
15:46
Do not allocate so much surplus memory in the implementation of the replace() function. (CVS 3951) (check-in: 0cf518ceeb user: drh tags: trunk)
15:34
Limit the length of the patterns on LIKE and GLOB to avoid problems with deep recursion and N^2 behavior. (CVS 3950) (check-in: 42e6c82699 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/func.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** 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.150 2007/05/08 15:34:48 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/* #include <math.h> */
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** 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.151 2007/05/08 15:46:18 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/* #include <math.h> */
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
744
745
746
747
748
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

778
779
780
781




782
783
784
785
786
787

788
789
790
791
792
793
794
  const unsigned char *zStr;        /* The input string A */
  const unsigned char *zPattern;    /* The pattern string B */
  const unsigned char *zRep;        /* The replacement string C */
  unsigned char *zOut;              /* The output */
  int nStr;                /* Size of zStr */
  int nPattern;            /* Size of zPattern */
  int nRep;                /* Size of zRep */
  int nOut;                /* Maximum size of zOut */
  int loopLimit;           /* Last zStr[] that might match zPattern[] */
  int i, j;                /* Loop counters */

  assert( argc==3 );
  nStr = sqlite3_value_bytes(argv[0]);
  zStr = sqlite3_value_text(argv[0]);
  if( zStr==0 ) return;
  nPattern = sqlite3_value_bytes(argv[1]);
  zPattern = sqlite3_value_text(argv[1]);
  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_toobig(context);
        sqlite3_free(zOut);
        return;




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

  memcpy(&zOut[j], &zStr[i], nStr-i);
  j += nStr - i;
  assert( j<=nOut );
  zOut[j] = 0;
  sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);
}








|













<
|
<
<
|
<
|
|
>
>





>
|



>
>
>
>






>







744
745
746
747
748
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
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  const unsigned char *zStr;        /* The input string A */
  const unsigned char *zPattern;    /* The pattern string B */
  const unsigned char *zRep;        /* The replacement string C */
  unsigned char *zOut;              /* The output */
  int nStr;                /* Size of zStr */
  int nPattern;            /* Size of zPattern */
  int nRep;                /* Size of zRep */
  i64 nOut;                /* Maximum size of zOut */
  int loopLimit;           /* Last zStr[] that might match zPattern[] */
  int i, j;                /* Loop counters */

  assert( argc==3 );
  nStr = sqlite3_value_bytes(argv[0]);
  zStr = sqlite3_value_text(argv[0]);
  if( zStr==0 ) return;
  nPattern = sqlite3_value_bytes(argv[1]);
  zPattern = sqlite3_value_text(argv[1]);
  if( zPattern==0 || zPattern[0]==0 ) return;
  nRep = sqlite3_value_bytes(argv[2]);
  zRep = sqlite3_value_text(argv[2]);
  if( zRep==0 ) return;

  nOut = nStr + 1;


  assert( nOut<SQLITE_MAX_LENGTH );

  zOut = sqlite3_malloc((int)nOut);
  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{
      nOut += nRep - nPattern;
      if( nOut>=SQLITE_MAX_LENGTH ){
        sqlite3_result_error_toobig(context);
        sqlite3_free(zOut);
        return;
      }
      zOut = sqlite3_realloc(zOut, (int)nOut);
      if( zOut==0 ){
        return;
      }
      memcpy(&zOut[j], zRep, nRep);
      j += nRep;
      i += nPattern-1;
    }
  }
  assert( j+nStr-i+1==nOut );
  memcpy(&zOut[j], &zStr[i], nStr-i);
  j += nStr - i;
  assert( j<=nOut );
  zOut[j] = 0;
  sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);
}