Index: Makefile.msc
==================================================================
--- Makefile.msc
+++ Makefile.msc
@@ -1563,11 +1563,11 @@
# <>
sqlite3.def: libsqlite3.lib
echo EXPORTS > sqlite3.def
dumpbin /all libsqlite3.lib \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset)?_[^@]*)(?:@\d+)?$$" \1 \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup)?_[^@]*)(?:@\d+)?$$" \1 \
| sort >> sqlite3.def
# <>
$(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \
Index: autoconf/Makefile.am
==================================================================
--- autoconf/Makefile.am
+++ autoconf/Makefile.am
@@ -10,11 +10,11 @@
EXTRA_sqlite3_SOURCES = sqlite3.c
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
-include_HEADERS = sqlite3.h sqlite3ext.h
+include_HEADERS = sqlite3.h sqlite3ext.h msvc.h
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs
pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = sqlite3.pc
Index: autoconf/Makefile.msc
==================================================================
--- autoconf/Makefile.msc
+++ autoconf/Makefile.msc
@@ -19,11 +19,11 @@
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
#
!IFNDEF USE_FULLWARN
-USE_FULLWARN = 0
+USE_FULLWARN = 1
!ENDIF
# Set this non-0 to enable treating warnings as errors (-WX, etc) when
# compiling.
#
@@ -952,11 +952,11 @@
$(CSC) /target:exe $(TOP)\Replace.cs
sqlite3.def: Replace.exe $(LIBOBJ)
echo EXPORTS > sqlite3.def
dumpbin /all $(LIBOBJ) \
- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
+ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| sort >> sqlite3.def
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
Index: ext/fts5/fts5_buffer.c
==================================================================
--- ext/fts5/fts5_buffer.c
+++ ext/fts5/fts5_buffer.c
@@ -65,13 +65,15 @@
Fts5Buffer *pBuf,
u32 nData,
const u8 *pData
){
assert_nc( *pRc || nData>=0 );
- if( fts5BufferGrow(pRc, pBuf, nData) ) return;
- memcpy(&pBuf->p[pBuf->n], pData, nData);
- pBuf->n += nData;
+ if( nData ){
+ if( fts5BufferGrow(pRc, pBuf, nData) ) return;
+ memcpy(&pBuf->p[pBuf->n], pData, nData);
+ pBuf->n += nData;
+ }
}
/*
** Append the nul-terminated string zStr to the buffer pBuf. This function
** ensures that the byte following the buffer data is set to 0x00, even
@@ -244,12 +246,12 @@
void *sqlite3Fts5MallocZero(int *pRc, int nByte){
void *pRet = 0;
if( *pRc==SQLITE_OK ){
pRet = sqlite3_malloc(nByte);
- if( pRet==0 && nByte>0 ){
- *pRc = SQLITE_NOMEM;
+ if( pRet==0 ){
+ if( nByte>0 ) *pRc = SQLITE_NOMEM;
}else{
memset(pRet, 0, nByte);
}
}
return pRet;
Index: ext/fts5/fts5_hash.c
==================================================================
--- ext/fts5/fts5_hash.c
+++ ext/fts5/fts5_hash.c
@@ -34,13 +34,14 @@
Fts5HashEntry **aSlot; /* Array of hash slots */
};
/*
** Each entry in the hash table is represented by an object of the
-** following type. Each object, its key (zKey[]) and its current data
-** are stored in a single memory allocation. The position list data
-** immediately follows the key data in memory.
+** following type. Each object, its key (a nul-terminated string) and
+** its current data are stored in a single memory allocation. The
+** key immediately follows the object in memory. The position list
+** data immediately follows the key data in memory.
**
** The data that follows the key is in a similar, but not identical format
** to the doclist data stored in the database. It is:
**
** * Rowid, as a varint
@@ -60,24 +61,24 @@
Fts5HashEntry *pScanNext; /* Next entry in sorted order */
int nAlloc; /* Total size of allocation */
int iSzPoslist; /* Offset of space for 4-byte poslist size */
int nData; /* Total bytes of data (incl. structure) */
- int nKey; /* Length of zKey[] in bytes */
+ int nKey; /* Length of key in bytes */
u8 bDel; /* Set delete-flag @ iSzPoslist */
u8 bContent; /* Set content-flag (detail=none mode) */
i16 iCol; /* Column of last value written */
int iPos; /* Position of last value written */
i64 iRowid; /* Rowid of last value written */
- char zKey[8]; /* Nul-terminated entry key */
};
/*
-** Size of Fts5HashEntry without the zKey[] array.
+** Eqivalent to:
+**
+** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
*/
-#define FTS5_HASHENTRYSIZE (sizeof(Fts5HashEntry)-8)
-
+#define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
/*
** Allocate a new hash table.
*/
@@ -171,11 +172,11 @@
for(i=0; inSlot; i++){
while( apOld[i] ){
int iHash;
Fts5HashEntry *p = apOld[i];
apOld[i] = p->pHashNext;
- iHash = fts5HashKey(nNew, (u8*)p->zKey, (int)strlen(p->zKey));
+ iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), strlen(fts5EntryKey(p)));
p->pHashNext = apNew[iHash];
apNew[iHash] = p;
}
}
@@ -242,22 +243,24 @@
bNew = (pHash->eDetail==FTS5_DETAIL_FULL);
/* Attempt to locate an existing hash entry */
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
- if( p->zKey[0]==bByte
+ char *zKey = fts5EntryKey(p);
+ if( zKey[0]==bByte
&& p->nKey==nToken
- && memcmp(&p->zKey[1], pToken, nToken)==0
+ && memcmp(&zKey[1], pToken, nToken)==0
){
break;
}
}
/* If an existing hash entry cannot be found, create a new one. */
if( p==0 ){
/* Figure out how much space to allocate */
- int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
+ char *zKey;
+ int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
if( nByte<128 ) nByte = 128;
/* Grow the Fts5Hash.aSlot[] array if necessary. */
if( (pHash->nEntry*2)>=pHash->nSlot ){
int rc = fts5HashResize(pHash);
@@ -266,18 +269,19 @@
}
/* Allocate new Fts5HashEntry and add it to the hash table. */
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
if( !p ) return SQLITE_NOMEM;
- memset(p, 0, FTS5_HASHENTRYSIZE);
+ memset(p, 0, sizeof(Fts5HashEntry));
p->nAlloc = nByte;
- p->zKey[0] = bByte;
- memcpy(&p->zKey[1], pToken, nToken);
- assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) );
+ zKey = fts5EntryKey(p);
+ zKey[0] = bByte;
+ memcpy(&zKey[1], pToken, nToken);
+ assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
p->nKey = nToken;
- p->zKey[nToken+1] = '\0';
- p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
+ zKey[nToken+1] = '\0';
+ p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry);
p->pHashNext = pHash->aSlot[iHash];
pHash->aSlot[iHash] = p;
pHash->nEntry++;
/* Add the first rowid field to the hash-entry */
@@ -391,13 +395,15 @@
}else if( p2==0 ){
*ppOut = p1;
p1 = 0;
}else{
int i = 0;
- while( p1->zKey[i]==p2->zKey[i] ) i++;
+ char *zKey1 = fts5EntryKey(p1);
+ char *zKey2 = fts5EntryKey(p2);
+ while( zKey1[i]==zKey2[i] ) i++;
- if( ((u8)p1->zKey[i])>((u8)p2->zKey[i]) ){
+ if( ((u8)zKey1[i])>((u8)zKey2[i]) ){
/* p2 is smaller */
*ppOut = p2;
ppOut = &p2->pScanNext;
p2 = p2->pScanNext;
}else{
@@ -436,11 +442,11 @@
memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
for(iSlot=0; iSlotnSlot; iSlot++){
Fts5HashEntry *pIter;
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
- if( pTerm==0 || 0==memcmp(pIter->zKey, pTerm, nTerm) ){
+ if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
Fts5HashEntry *pEntry = pIter;
pEntry->pScanNext = 0;
for(i=0; ap[i]; i++){
pEntry = fts5HashEntryMerge(pEntry, ap[i]);
ap[i] = 0;
@@ -469,20 +475,22 @@
const char *pTerm, int nTerm, /* Query term */
const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */
int *pnDoclist /* OUT: Size of doclist in bytes */
){
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
+ char *zKey;
Fts5HashEntry *p;
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
- if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break;
+ zKey = fts5EntryKey(p);
+ if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
}
if( p ){
fts5HashAddPoslistSize(pHash, p);
- *ppDoclist = (const u8*)&p->zKey[nTerm+1];
- *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
+ *ppDoclist = (const u8*)&zKey[nTerm+1];
+ *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
}else{
*ppDoclist = 0;
*pnDoclist = 0;
}
@@ -511,17 +519,18 @@
const u8 **ppDoclist, /* OUT: pointer to doclist */
int *pnDoclist /* OUT: size of doclist in bytes */
){
Fts5HashEntry *p;
if( (p = pHash->pScan) ){
- int nTerm = (int)strlen(p->zKey);
+ char *zKey = fts5EntryKey(p);
+ int nTerm = (int)strlen(zKey);
fts5HashAddPoslistSize(pHash, p);
- *pzTerm = p->zKey;
- *ppDoclist = (const u8*)&p->zKey[nTerm+1];
- *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
+ *pzTerm = zKey;
+ *ppDoclist = (const u8*)&zKey[nTerm+1];
+ *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
}else{
*pzTerm = 0;
*ppDoclist = 0;
*pnDoclist = 0;
}
}
Index: ext/fts5/fts5_index.c
==================================================================
--- ext/fts5/fts5_index.c
+++ ext/fts5/fts5_index.c
@@ -5091,11 +5091,11 @@
pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
if( pData ){
pData->p = (u8*)&pData[1];
pData->nn = pData->szLeaf = doclist.n;
- memcpy(pData->p, doclist.p, doclist.n);
+ if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
fts5MultiIterNew2(p, pData, bDesc, ppIter);
}
fts5BufferFree(&doclist);
}
@@ -5330,11 +5330,11 @@
/* If the QUERY_SCAN flag is set, all other flags must be clear. */
assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
- memcpy(&buf.p[1], pToken, nToken);
+ if( nToken ) memcpy(&buf.p[1], pToken, nToken);
/* Figure out which index to search and set iIdx accordingly. If this
** is a prefix query for which there is no prefix index, set iIdx to
** greater than pConfig->nPrefix to indicate that the query will be
** satisfied by scanning multiple terms in the main index.
@@ -5379,11 +5379,11 @@
if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
}
}
if( p->rc ){
- sqlite3Fts5IterClose(&pRet->base);
+ sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
pRet = 0;
fts5CloseReader(p);
}
*ppIter = &pRet->base;
Index: src/expr.c
==================================================================
--- src/expr.c
+++ src/expr.c
@@ -350,11 +350,10 @@
}else{
return 1;
}
}
-#ifndef SQLITE_OMIT_SUBQUERY
/*
** Return a pointer to a subexpression of pVector that is the i-th
** column of the vector (numbered starting with 0). The caller must
** ensure that i is within range.
**
@@ -378,13 +377,11 @@
return pVector->x.pList->a[i].pExpr;
}
}
return pVector;
}
-#endif /* !defined(SQLITE_OMIT_SUBQUERY) */
-#ifndef SQLITE_OMIT_SUBQUERY
/*
** Compute and return a new Expr object which when passed to
** sqlite3ExprCode() will generate all necessary code to compute
** the iField-th column of the vector expression pVector.
**
@@ -438,11 +435,10 @@
if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
pRet = sqlite3ExprDup(pParse->db, pVector, 0);
}
return pRet;
}
-#endif /* !define(SQLITE_OMIT_SUBQUERY) */
/*
** If expression pExpr is of type TK_SELECT, generate code to evaluate
** it. Return the register in which the result is stored (or, if the
** sub-select returns more than one column, the first in an array
@@ -3409,11 +3405,15 @@
if( nResult==1 ){
iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable);
}else{
*piFreeable = 0;
if( p->op==TK_SELECT ){
+#if SQLITE_OMIT_SUBQUERY
+ iResult = 0;
+#else
iResult = sqlite3CodeSubselect(pParse, p, 0, 0);
+#endif
}else{
int i;
iResult = pParse->nMem+1;
pParse->nMem += nResult;
for(i=0; iflags & MEM_Blob );
+ rc = ExpandBlob(pIn3);
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ if( rc ) goto no_mem;
pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
- assert( pIn3->flags & MEM_Blob );
- (void)ExpandBlob(pIn3);
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
}
pIdxKey->default_rc = 0;
takeJump = 0;
if( pOp->opcode==OP_NoConflict ){
Index: test/auth.test
==================================================================
--- test/auth.test
+++ test/auth.test
@@ -2522,9 +2522,31 @@
} [list \
SQLITE_SELECT {} {} {} {} \
SQLITE_READ t6 a main {} \
SQLITE_READ t7 {} {} {} \
]
+
+# Test also that if SQLITE_DENY is returned from an SQLITE_READ authorizer
+# invocation with no column name specified, compilation fails.
+#
+set ::authargs [list]
+proc auth {op a b c d} {
+ lappend ::authargs $op $a $b $c $d
+ if {$op == "SQLITE_READ"} { return "SQLITE_DENY" }
+ return "SQLITE_OK"
+}
+set ::authargs [list]
+do_catchsql_test auth-8.3 {
+ SELECT count(*) FROM t7
+} {1 {not authorized}}
+do_test auth-8.4 {
+ set ::authargs
+} [list \
+ SQLITE_SELECT {} {} {} {} \
+ SQLITE_FUNCTION {} count {} {} \
+ SQLITE_READ t7 {} {} {} \
+]
+
rename proc {}
rename proc_real proc
finish_test
Index: tool/mkautoconfamal.sh
==================================================================
--- tool/mkautoconfamal.sh
+++ tool/mkautoconfamal.sh
@@ -49,10 +49,11 @@
cp sqlite3.c $TMPSPACE
cp sqlite3.h $TMPSPACE
cp sqlite3ext.h $TMPSPACE
cp $TOP/sqlite3.1 $TMPSPACE
cp $TOP/sqlite3.pc.in $TMPSPACE
+cp $TOP/src/msvc.h $TMPSPACE
cp $TOP/src/shell.c $TMPSPACE
cp $TOP/src/sqlite3.rc $TMPSPACE
cp $TOP/tool/Replace.cs $TMPSPACE
cat $TMPSPACE/configure.ac |
Index: tool/mkmsvcmin.tcl
==================================================================
--- tool/mkmsvcmin.tcl
+++ tool/mkmsvcmin.tcl
@@ -81,11 +81,11 @@
$(CSC) /target:exe $(TOP)\Replace.cs
sqlite3.def: Replace.exe $(LIBOBJ)
echo EXPORTS > sqlite3.def
dumpbin /all $(LIBOBJ) \\
- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
+ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
| sort >> sqlite3.def
}]]
set data "#### DO NOT EDIT ####\n"
append data "# This makefile is automatically "
Index: tool/mksqlite3h.tcl
==================================================================
--- tool/mksqlite3h.tcl
+++ tool/mksqlite3h.tcl
@@ -79,10 +79,13 @@
{^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3session_[_a-zA-Z0-9]+)(\(.*)$}
set declpattern3 \
{^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changeset_[_a-zA-Z0-9]+)(\(.*)$}
+set declpattern4 \
+ {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changegroup_[_a-zA-Z0-9]+)(\(.*)$}
+
# Force the output to use unix line endings, even on Windows.
fconfigure stdout -translation lf
set filelist [subst {
$TOP/src/sqlite.h.in
@@ -127,11 +130,12 @@
if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
set line "SQLITE_API $line"
} else {
if {[regexp $declpattern1 $line all rettype funcname rest] || \
[regexp $declpattern2 $line all rettype funcname rest] || \
- [regexp $declpattern3 $line all rettype funcname rest]} {
+ [regexp $declpattern3 $line all rettype funcname rest] || \
+ [regexp $declpattern4 $line all rettype funcname rest]} {
set line SQLITE_API
append line " " [string trim $rettype]
if {[string index $rettype end] ne "*"} {
append line " "
}
Index: tool/omittest.tcl
==================================================================
--- tool/omittest.tcl
+++ tool/omittest.tcl
@@ -1,8 +1,5 @@
-
-set rcsid {$Id: omittest.tcl,v 1.8 2008/10/13 15:35:09 drh Exp $}
-
# Documentation for this script. This may be output to stderr
# if the script is invoked incorrectly.
set ::USAGE_MESSAGE {
This Tcl script is used to test the various compile time options
available for omitting code (the SQLITE_OMIT_xxx options). It
@@ -132,29 +129,40 @@
}
set ::SKIP_RUN 0 ;# Default to attempt test
set ::TARGET testfixture ;# Default thing to build
for {set i 0} {$i < [llength $argv]} {incr i} {
- switch -- [lindex $argv $i] {
- -makefile {
+ switch -regexp -- [lindex $argv $i] {
+ -{1,2}makefile {
incr i
set ::MAKEFILE [lindex $argv $i]
}
- -nmake {
+ -{1,2}nmake {
set ::MAKEBIN nmake
set ::MAKEFILE ./Makefile.msc
}
- -target {
+ -{1,2}target {
incr i
set ::TARGET [lindex $argv $i]
}
- -skip_run {
+ -{1,2}skip_run {
set ::SKIP_RUN 1
}
+
+ -{1,2}help {
+ puts $::USAGE_MESSAGE
+ exit
+ }
+
+ -.* {
+ puts stderr "Unknown option: [lindex $argv i]"
+ puts stderr $::USAGE_MESSAGE
+ exit 1
+ }
default {
if {[info exists ::SYMBOL]} {
puts stderr [string trim $::USAGE_MESSAGE]
exit -1
Index: tool/warnings.sh
==================================================================
--- tool/warnings.sh
+++ tool/warnings.sh
@@ -2,17 +2,19 @@
#
# Run this script in a directory with a working makefile to check for
# compiler warnings in SQLite.
#
-# Use these for testing on Linux and Mac OSX:
-WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
-WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
-
-# Use these for testing on OpenBSD:
-# WARNING_OPTS=-Wall
-# WARNING_ANDROID_OPTS=-Wall
+if uname | grep -i openbsd ; then
+ # Use these for testing on OpenBSD:
+ WARNING_OPTS=-Wall
+ WARNING_ANDROID_OPTS=-Wall
+else
+ # Use these for testing on Linux and Mac OSX:
+ WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
+ WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
+fi
rm -f sqlite3.c
make sqlite3.c
echo '********** No optimizations. Includes FTS4/5, RTREE, JSON1 ***'
echo '********** ' Options: $WARNING_OPTS