/ Check-in [a9e81908]
Login

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

Overview
Comment:Changes to avoid undefined behavior detected by analysis tools - never observed in the wild. Later: This check-in introduces a bug, fixed at [a304e34675404aee].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a9e819082ba19e72db03bba37edfb7702ff489a5
User & Date: drh 2015-12-07 16:43:44
Original Comment: Changes to avoid obscure, theoretical undefined behavior. This is preventative measures only - no actual problems observed on tested compilers.
References
2016-01-01
16:26
Avoid misaligned memory allocations on Sparc in sqlite3VdbeMakeReady(). This fixes a problem introduced by check-in [a9e819082b]. check-in: a304e346 user: drh tags: trunk
2015-12-11
04:11
Fix a memory allocation bug introduced last week by check-in [a9e819082ba]. The bug only appears on systems where the size of a structure is not always a multiple of 8 - which in practice means only on 32-bit windows systems. check-in: 96d3e99f user: drh tags: trunk
Context
2015-12-08
19:50
Experimental optimization for DELETE statements with WHERE clauses that qualify for the OR-optimization. check-in: d52376df user: dan tags: onepass-delete-or
2015-12-07
18:18
Fix the openDirectory() routine in the unix VFS so that it works for databases located in the root of the filesystem and for database files that have no pathname at all. check-in: e7ae120d user: drh tags: trunk
16:43
Changes to avoid undefined behavior detected by analysis tools - never observed in the wild. Later: This check-in introduces a bug, fixed at [a304e34675404aee]. check-in: a9e81908 user: drh tags: trunk
2015-12-04
13:44
Remove the dependence on "exec ls -U" from the vtabH.test module, as the -U option to "ls" is not universally available. check-in: 4ecbc75b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/printf.c.

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
    if( p->db ){
      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
    }else{
      zNew = sqlite3_realloc64(zOld, p->nAlloc);
    }
    if( zNew ){
      assert( p->zText!=0 || p->nChar==0 );
      if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
      p->zText = zNew;
      p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
    }else{
      sqlite3StrAccumReset(p);
      setStrAccumError(p, STRACCUM_NOMEM);
      return 0;
    }







|







784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
    if( p->db ){
      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
    }else{
      zNew = sqlite3_realloc64(zOld, p->nAlloc);
    }
    if( zNew ){
      assert( p->zText!=0 || p->nChar==0 );
      if( p->zText==p->zBase && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
      p->zText = zNew;
      p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
    }else{
      sqlite3StrAccumReset(p);
      setStrAccumError(p, STRACCUM_NOMEM);
      return 0;
    }

Changes to src/test1.c.

5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
    Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
    return TCL_ERROR;
  }
  if( logcallback.pObj ){
    Tcl_DecrRefCount(logcallback.pObj);
    logcallback.pObj = 0;
    logcallback.pInterp = 0;
    sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
  }
  if( objc>1 ){
    logcallback.pObj = objv[1];
    Tcl_IncrRefCount(logcallback.pObj);
    logcallback.pInterp = interp;
    sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
  }
  return TCL_OK;
}

/*
**     tcl_objproc COMMANDNAME ARGS...
**







|





|







5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
    Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
    return TCL_ERROR;
  }
  if( logcallback.pObj ){
    Tcl_DecrRefCount(logcallback.pObj);
    logcallback.pObj = 0;
    logcallback.pInterp = 0;
    sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
  }
  if( objc>1 ){
    logcallback.pObj = objv[1];
    Tcl_IncrRefCount(logcallback.pObj);
    logcallback.pInterp = interp;
    sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
  }
  return TCL_OK;
}

/*
**     tcl_objproc COMMANDNAME ARGS...
**

Changes to src/test_malloc.c.

218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
    ** a zeroed allocator then calling GETMALLOC. */
    memset(&m2, 0, sizeof(m2));
    sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
    sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
    assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );

    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);

  }

  if( rc==SQLITE_OK ){
    memfault.isInstalled = 1;
  }
  return rc;
}







|
>







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    ** a zeroed allocator then calling GETMALLOC. */
    memset(&m2, 0, sizeof(m2));
    sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
    sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
    assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );

    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
        (void*)0, (void*)0);
  }

  if( rc==SQLITE_OK ){
    memfault.isInstalled = 1;
  }
  return rc;
}

Changes to src/vdbeaux.c.

1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745
1746
1747
1748

1749
1750
1751


1752
1753
1754
1755
1756
1757
1758
....
1817
1818
1819
1820
1821
1822
1823

1824
1825
1826
1827
1828
1829
1830
1831
1832
....
1850
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
....
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
** NULL, it means that memory space has already been allocated and that
** this routine should not allocate any new memory.  When pBuf is not
** NULL simply return pBuf.  Only allocate new memory space when pBuf
** is NULL.
**
** nByte is the number of bytes of space needed.
**
** *ppFrom points to available space and pEnd points to the end of the
** available space.  When space is allocated, *ppFrom is advanced past
** the end of the allocated space.
**
** *pnByte is a counter of the number of bytes of space that have failed
** to allocate.  If there is insufficient space in *ppFrom to satisfy the
** request, then increment *pnByte by the amount of the request.
*/
static void *allocSpace(
  void *pBuf,          /* Where return pointer will be stored */
  int nByte,           /* Number of bytes to allocate */

  u8 **ppFrom,         /* IN/OUT: Allocate from *ppFrom */
  u8 *pEnd,            /* Pointer to 1 byte past the end of *ppFrom buffer */
  int *pnByte          /* If allocation cannot be made, increment *pnByte */
){
  assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) );
  if( pBuf ) return pBuf;
  nByte = ROUND8(nByte);
  if( &(*ppFrom)[nByte] <= pEnd ){
    pBuf = (void*)*ppFrom;
    *ppFrom += nByte;

  }else{
    *pnByte += nByte;
  }


  return pBuf;
}

/*
** Rewind the VDBE back to the beginning in preparation for
** running it.
*/
................................................................................
  sqlite3 *db;                   /* The database connection */
  int nVar;                      /* Number of parameters */
  int nMem;                      /* Number of VM memory registers */
  int nCursor;                   /* Number of cursors required */
  int nArg;                      /* Number of arguments in subprograms */
  int nOnce;                     /* Number of OP_Once instructions */
  int n;                         /* Loop counter */

  u8 *zCsr;                      /* Memory available for allocation */
  u8 *zEnd;                      /* First byte past allocated memory */
  int nByte;                     /* How much extra memory is needed */

  assert( p!=0 );
  assert( p->nOp>0 );
  assert( pParse!=0 );
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( pParse==p->pParse );
................................................................................
  */
  nMem += nCursor;

  /* Allocate space for memory registers, SQL variables, VDBE cursors and 
  ** an array to marshal SQL function arguments in.
  */
  zCsr = (u8*)&p->aOp[p->nOp];            /* Memory avaliable for allocation */
  zEnd = (u8*)&p->aOp[pParse->nOpAlloc];  /* First byte past end of zCsr[] */


  resolveP2Values(p, &nArg);
  p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
  if( pParse->explain && nMem<10 ){
    nMem = 10;
  }
  memset(zCsr, 0, zEnd-zCsr);
  zCsr += (zCsr - (u8*)0)&7;
  assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
  p->expired = 0;

  /* Memory for registers, parameters, cursor, etc, is allocated in two
  ** passes.  On the first pass, we try to reuse unused space at the 
  ** end of the opcode array.  If we are unable to satisfy all memory
................................................................................
  **
  ** This two-pass approach that reuses as much memory as possible from
  ** the leftover space at the end of the opcode array can significantly
  ** reduce the amount of memory held by a prepared statement.
  */
  do {
    nByte = 0;
    p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
    p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
    p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
    p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
    p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
                          &zCsr, zEnd, &nByte);
    p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), &zCsr, zEnd, &nByte);
#endif
    if( nByte ){
      p->pFree = sqlite3DbMallocZero(db, nByte);
    }
    zCsr = p->pFree;
    zEnd = &zCsr[nByte];
  }while( nByte && !db->mallocFailed );

  p->nCursor = nCursor;
  p->nOnceFlag = nOnce;
  if( p->aVar ){
    p->nVar = (ynVar)nVar;
    for(n=0; n<nVar; n++){







|
|
<

|
|
|




>
|
<
|

|
|
|
|
<
|
>
|
|
|
>
>







 







>

<







 







|
>






|







 







|
|
|
|

|
|

|





|







1721
1722
1723
1724
1725
1726
1727
1728
1729

1730
1731
1732
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
....
1818
1819
1820
1821
1822
1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833
....
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
....
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
** NULL, it means that memory space has already been allocated and that
** this routine should not allocate any new memory.  When pBuf is not
** NULL simply return pBuf.  Only allocate new memory space when pBuf
** is NULL.
**
** nByte is the number of bytes of space needed.
**
** pFrom points to *pnFrom bytes of available space.  New space is allocated
** from the end of the pFrom buffer and *pnFrom is decremented.

**
** *pnNeeded is a counter of the number of bytes of space that have failed
** to allocate.  If there is insufficient space in pFrom to satisfy the
** request, then increment *pnNeeded by the amount of the request.
*/
static void *allocSpace(
  void *pBuf,          /* Where return pointer will be stored */
  int nByte,           /* Number of bytes to allocate */
  u8 *pFrom,           /* Memory available for allocation */
  int *pnFrom,         /* IN/OUT: Space available at pFrom */

  int *pnNeeded        /* If allocation cannot be made, increment *pnByte */
){
  assert( EIGHT_BYTE_ALIGNMENT(pFrom) );
  if( pBuf==0 ){
    nByte = ROUND8(nByte);
    if( nByte <= *pnFrom ){

      *pnFrom -= nByte;
      pBuf = &pFrom[*pnFrom];
    }else{
      *pnNeeded += nByte;
    }
  }
  assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
  return pBuf;
}

/*
** Rewind the VDBE back to the beginning in preparation for
** running it.
*/
................................................................................
  sqlite3 *db;                   /* The database connection */
  int nVar;                      /* Number of parameters */
  int nMem;                      /* Number of VM memory registers */
  int nCursor;                   /* Number of cursors required */
  int nArg;                      /* Number of arguments in subprograms */
  int nOnce;                     /* Number of OP_Once instructions */
  int n;                         /* Loop counter */
  int nFree;                     /* Available free space */
  u8 *zCsr;                      /* Memory available for allocation */

  int nByte;                     /* How much extra memory is needed */

  assert( p!=0 );
  assert( p->nOp>0 );
  assert( pParse!=0 );
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( pParse==p->pParse );
................................................................................
  */
  nMem += nCursor;

  /* Allocate space for memory registers, SQL variables, VDBE cursors and 
  ** an array to marshal SQL function arguments in.
  */
  zCsr = (u8*)&p->aOp[p->nOp];            /* Memory avaliable for allocation */
  assert( pParse->nOpAlloc*sizeof(Op) <= 0x7fffff00 );
  nFree = (pParse->nOpAlloc - p->nOp)*sizeof(p->aOp[0]); /* Available space */

  resolveP2Values(p, &nArg);
  p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
  if( pParse->explain && nMem<10 ){
    nMem = 10;
  }
  memset(zCsr, 0, nFree);
  zCsr += (zCsr - (u8*)0)&7;
  assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
  p->expired = 0;

  /* Memory for registers, parameters, cursor, etc, is allocated in two
  ** passes.  On the first pass, we try to reuse unused space at the 
  ** end of the opcode array.  If we are unable to satisfy all memory
................................................................................
  **
  ** This two-pass approach that reuses as much memory as possible from
  ** the leftover space at the end of the opcode array can significantly
  ** reduce the amount of memory held by a prepared statement.
  */
  do {
    nByte = 0;
    p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte);
    p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte);
    p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte);
    p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), zCsr, &nFree, &nByte);
    p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
                          zCsr, &nFree, &nByte);
    p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte);
#endif
    if( nByte ){
      p->pFree = sqlite3DbMallocZero(db, nByte);
    }
    zCsr = p->pFree;
    nFree = nByte;
  }while( nByte && !db->mallocFailed );

  p->nCursor = nCursor;
  p->nOnceFlag = nOnce;
  if( p->aVar ){
    p->nVar = (ynVar)nVar;
    for(n=0; n<nVar; n++){