/ Check-in [f20396ad]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Avoid doing comparisons with pointers that might have been previously been passed to realloc() and/or free().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f20396adb2cff12a17a3fc90b36241ae3fdfd62a
User & Date: drh 2015-12-08 16:08:10
Context
2015-12-08
16:58
Changes to avoid undefined behavior in memset() and memcpy() and in the comparisons of pointers from different allocations. All problems are found by analysis tools - none have been seen in the wild. check-in: 901d0b8f user: drh tags: trunk
16:08
Avoid doing comparisons with pointers that might have been previously been passed to realloc() and/or free(). check-in: f20396ad user: drh tags: trunk
04:18
Add a test case of the form "WHERE a<2 OR a<3" using PRAGMA count_changes. This test case was failing before the 3.9.0 release. check-in: 177862c1 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/printf.c.

   762    762       return 0;
   763    763     }
   764    764     if( p->mxAlloc==0 ){
   765    765       N = p->nAlloc - p->nChar - 1;
   766    766       setStrAccumError(p, STRACCUM_TOOBIG);
   767    767       return N;
   768    768     }else{
   769         -    char *zOld = (p->zText==p->zBase ? 0 : p->zText);
          769  +    char *zOld = p->bMalloced ? p->zText : 0;
   770    770       i64 szNew = p->nChar;
          771  +    assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) );
   771    772       szNew += N + 1;
   772    773       if( szNew+p->nChar<=p->mxAlloc ){
   773    774         /* Force exponential buffer size growth as long as it does not overflow,
   774    775         ** to avoid having to call this routine too often */
   775    776         szNew += p->nChar;
   776    777       }
   777    778       if( szNew > p->mxAlloc ){
................................................................................
   784    785       if( p->db ){
   785    786         zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
   786    787       }else{
   787    788         zNew = sqlite3_realloc64(zOld, p->nAlloc);
   788    789       }
   789    790       if( zNew ){
   790    791         assert( p->zText!=0 || p->nChar==0 );
   791         -      if( p->zText==p->zBase && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
          792  +      if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
   792    793         p->zText = zNew;
   793    794         p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
          795  +      p->bMalloced = 1;
   794    796       }else{
   795    797         sqlite3StrAccumReset(p);
   796    798         setStrAccumError(p, STRACCUM_NOMEM);
   797    799         return 0;
   798    800       }
   799    801     }
   800    802     return N;
................................................................................
   804    806   ** Append N copies of character c to the given string buffer.
   805    807   */
   806    808   void sqlite3AppendChar(StrAccum *p, int N, char c){
   807    809     testcase( p->nChar + (i64)N > 0x7fffffff );
   808    810     if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
   809    811       return;
   810    812     }
          813  +  assert( (p->zText==p->zBase)==(p->bMalloced==0) );
   811    814     while( (N--)>0 ) p->zText[p->nChar++] = c;
   812    815   }
   813    816   
   814    817   /*
   815    818   ** The StrAccum "p" is not large enough to accept N new bytes of z[].
   816    819   ** So enlarge if first, then do the append.
   817    820   **
................................................................................
   821    824   */
   822    825   static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
   823    826     N = sqlite3StrAccumEnlarge(p, N);
   824    827     if( N>0 ){
   825    828       memcpy(&p->zText[p->nChar], z, N);
   826    829       p->nChar += N;
   827    830     }
          831  +  assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) );
   828    832   }
   829    833   
   830    834   /*
   831    835   ** Append N bytes of text from z to the StrAccum object.  Increase the
   832    836   ** size of the memory allocation for StrAccum if necessary.
   833    837   */
   834    838   void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
................................................................................
   856    860   /*
   857    861   ** Finish off a string by making sure it is zero-terminated.
   858    862   ** Return a pointer to the resulting string.  Return a NULL
   859    863   ** pointer if any kind of error was encountered.
   860    864   */
   861    865   char *sqlite3StrAccumFinish(StrAccum *p){
   862    866     if( p->zText ){
          867  +    assert( (p->zText==p->zBase)==(p->bMalloced==0) );
   863    868       p->zText[p->nChar] = 0;
   864         -    if( p->mxAlloc>0 && p->zText==p->zBase ){
          869  +    if( p->mxAlloc>0 && p->bMalloced==0 ){
   865    870         p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
   866    871         if( p->zText ){
   867    872           memcpy(p->zText, p->zBase, p->nChar+1);
          873  +        p->bMalloced = 1;
   868    874         }else{
   869    875           setStrAccumError(p, STRACCUM_NOMEM);
   870    876         }
   871    877       }
   872    878     }
   873    879     return p->zText;
   874    880   }
   875    881   
   876    882   /*
   877    883   ** Reset an StrAccum string.  Reclaim all malloced memory.
   878    884   */
   879    885   void sqlite3StrAccumReset(StrAccum *p){
   880         -  if( p->zText!=p->zBase ){
          886  +  assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) );
          887  +  if( p->bMalloced ){
   881    888       sqlite3DbFree(p->db, p->zText);
          889  +    p->bMalloced = 0;
   882    890     }
   883    891     p->zText = 0;
   884    892   }
   885    893   
   886    894   /*
   887    895   ** Initialize a string accumulator.
   888    896   **
................................................................................
   900    908   void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
   901    909     p->zText = p->zBase = zBase;
   902    910     p->db = db;
   903    911     p->nChar = 0;
   904    912     p->nAlloc = n;
   905    913     p->mxAlloc = mx;
   906    914     p->accError = 0;
          915  +  p->bMalloced = 0;
   907    916   }
   908    917   
   909    918   /*
   910    919   ** Print into memory obtained from sqliteMalloc().  Use the internal
   911    920   ** %-conversion extensions.
   912    921   */
   913    922   char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){

Changes to src/sqliteInt.h.

  2948   2948     sqlite3 *db;         /* Optional database for lookaside.  Can be NULL */
  2949   2949     char *zBase;         /* A base allocation.  Not from malloc. */
  2950   2950     char *zText;         /* The string collected so far */
  2951   2951     int  nChar;          /* Length of the string so far */
  2952   2952     int  nAlloc;         /* Amount of space allocated in zText */
  2953   2953     int  mxAlloc;        /* Maximum allowed allocation.  0 for no malloc usage */
  2954   2954     u8   accError;       /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
         2955  +  u8   bMalloced;      /* zText points to allocated space */
  2955   2956   };
  2956   2957   #define STRACCUM_NOMEM   1
  2957   2958   #define STRACCUM_TOOBIG  2
  2958   2959   
  2959   2960   /*
  2960   2961   ** A pointer to this structure is used to communicate information
  2961   2962   ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.