1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Fix a segfault in the streaming API functions triggered by a very long table name.

FossilOrigin-Name: d2642543eed54da1ac0f757d43dd4d72482eb752
This commit is contained in:
dan
2014-09-27 16:33:09 +00:00
parent 16228167c2
commit e8fa8c9649
6 changed files with 127 additions and 66 deletions

View File

@ -524,4 +524,30 @@ do_test 9.2 {
do_changeset_test 9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}} do_changeset_test 9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}}
S delete S delete
catch { db2 close } catch { db2 close }
#-------------------------------------------------------------------------
# Test a really long table name.
#
reset_db
set tblname [string repeat tblname123 100]
do_test 10.1.1 {
execsql "
CREATE TABLE $tblname (a PRIMARY KEY, b);
INSERT INTO $tblname VALUES('xyz', 'def');
"
sqlite3session S db main
S attach $tblname
execsql "
INSERT INTO $tblname VALUES('uvw', 'abc');
DELETE FROM $tblname WHERE a = 'xyz';
"
} {}
breakpoint
do_changeset_test 10.1.2 S "
{INSERT $tblname 0 X. {} {t uvw t abc}}
{DELETE $tblname 0 X. {t xyz t def} {}}
"
do_test 10.1.4 { S delete } {}
finish_test finish_test

View File

@ -30,7 +30,6 @@ do_common_sql {
faultsim_save_and_close faultsim_save_and_close
db2 close db2 close
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test OOM error handling when collecting and applying a simple changeset. # Test OOM error handling when collecting and applying a simple changeset.
# #
@ -234,7 +233,7 @@ set changeset [changeset_from_sql {
}] }]
db close db close
do_faultsim_test 5 -faults oom* -body { do_faultsim_test 5.1 -faults oom* -body {
set ::inverse [sqlite3changeset_invert $::changeset] set ::inverse [sqlite3changeset_invert $::changeset]
set {} {} set {} {}
} -test { } -test {
@ -251,6 +250,41 @@ do_faultsim_test 5 -faults oom* -body {
} }
} }
catch {db close}
catch {db2 close}
forcedelete test.db
sqlite3 db test.db
execsql {
CREATE TABLE t2(a PRIMARY KEY, b);
INSERT INTO t2 VALUES(1, 'abc');
INSERT INTO t2 VALUES(2, 'def');
}
set changeset [changeset_from_sql {
UPDATE t2 SET b = (b || b || b || b);
UPDATE t2 SET b = (b || b || b || b);
UPDATE t2 SET b = (b || b || b || b);
UPDATE t2 SET b = (b || b || b || b);
}]
db close
set abc [string repeat abc 256]
set def [string repeat def 256]
do_faultsim_test 5.2 -faults oom-tra* -body {
set ::inverse [sqlite3changeset_invert $::changeset]
set {} {}
} -test {
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
if {$testrc==0} {
set x [list]
sqlite3session_foreach c $::inverse { lappend x $c }
foreach c "
{UPDATE t2 0 X. {i 1 t $::abc} {{} {} t abc}}
{UPDATE t2 0 X. {i 2 t $::def} {{} {} t def}}
" { lappend y $c }
if {$x != $y} { error "changeset no good" }
}
}
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test that OOM errors in sqlite3changeset_concat() are handled correctly. # Test that OOM errors in sqlite3changeset_concat() are handled correctly.
# #

View File

@ -18,7 +18,7 @@ typedef struct SessionInput SessionInput;
** Minimum chunk size used by streaming versions of functions. ** Minimum chunk size used by streaming versions of functions.
*/ */
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
#define SESSIONS_STR_CHUNK_SIZE 1 #define SESSIONS_STR_CHUNK_SIZE 64
#else #else
#define SESSIONS_STR_CHUNK_SIZE 1024 #define SESSIONS_STR_CHUNK_SIZE 1024
#endif #endif
@ -1347,7 +1347,7 @@ static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){
int rc = *pRc; int rc = *pRc;
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
int nByte = 0; int nByte = 0;
sessionSerializeValue(0, pVal, &nByte); rc = sessionSerializeValue(0, pVal, &nByte);
sessionBufferGrow(p, nByte, &rc); sessionBufferGrow(p, nByte, &rc);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0); rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0);
@ -2225,12 +2225,10 @@ static int sessionReadRecord(
eType = pIn->aData[pIn->iNext++]; eType = pIn->aData[pIn->iNext++];
} }
assert( !apOut || apOut[i]==0 ); assert( apOut[i]==0 );
if( eType ){ if( eType ){
if( apOut ){ apOut[i] = sqlite3ValueNew(0);
apOut[i] = sqlite3ValueNew(0); if( !apOut[i] ) rc = SQLITE_NOMEM;
if( !apOut[i] ) rc = SQLITE_NOMEM;
}
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
@ -2239,22 +2237,20 @@ static int sessionReadRecord(
int nByte; int nByte;
pIn->iNext += sessionVarintGet(aVal, &nByte); pIn->iNext += sessionVarintGet(aVal, &nByte);
rc = sessionInputBuffer(pIn, nByte); rc = sessionInputBuffer(pIn, nByte);
if( apOut && rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
} }
pIn->iNext += nByte; pIn->iNext += nByte;
} }
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
if( apOut ){ sqlite3_int64 v = sessionGetI64(aVal);
sqlite3_int64 v = sessionGetI64(aVal); if( eType==SQLITE_INTEGER ){
if( eType==SQLITE_INTEGER ){ sqlite3VdbeMemSetInt64(apOut[i], v);
sqlite3VdbeMemSetInt64(apOut[i], v); }else{
}else{ double d;
double d; memcpy(&d, &v, 8);
memcpy(&d, &v, 8); sqlite3VdbeMemSetDouble(apOut[i], d);
sqlite3VdbeMemSetDouble(apOut[i], d);
}
} }
pIn->iNext += 8; pIn->iNext += 8;
} }
@ -2293,10 +2289,10 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){
while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){ while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){
nRead++; nRead++;
} }
if( pIn->aData[pIn->iNext + nRead]==0 ) break; if( (pIn->iNext + nRead)<pIn->nData ) break;
rc = sessionInputBuffer(pIn, nRead + 100); rc = sessionInputBuffer(pIn, nRead + 100);
} }
if( pnByte ) *pnByte = nRead+1; *pnByte = nRead+1;
return rc; return rc;
} }
@ -2775,7 +2771,7 @@ static int sessionChangesetInvert(
/* Write the new old.* record. Consists of the PK columns from the /* Write the new old.* record. Consists of the PK columns from the
** original old.* record, and the other values from the original ** original old.* record, and the other values from the original
** new.* record. */ ** new.* record. */
for(iCol=0; rc==SQLITE_OK && iCol<nCol; iCol++){ for(iCol=0; iCol<nCol; iCol++){
sqlite3_value *pVal = apVal[iCol + (abPK[iCol] ? 0 : nCol)]; sqlite3_value *pVal = apVal[iCol + (abPK[iCol] ? 0 : nCol)];
sessionAppendValue(&sOut, pVal, &rc); sessionAppendValue(&sOut, pVal, &rc);
} }
@ -2783,7 +2779,7 @@ static int sessionChangesetInvert(
/* Write the new new.* record. Consists of a copy of all values /* Write the new new.* record. Consists of a copy of all values
** from the original old.* record, except for the PK columns, which ** from the original old.* record, except for the PK columns, which
** are set to "undefined". */ ** are set to "undefined". */
for(iCol=0; rc==SQLITE_OK && iCol<nCol; iCol++){ for(iCol=0; iCol<nCol; iCol++){
sqlite3_value *pVal = (abPK[iCol] ? 0 : apVal[iCol]); sqlite3_value *pVal = (abPK[iCol] ? 0 : apVal[iCol]);
sessionAppendValue(&sOut, pVal, &rc); sessionAppendValue(&sOut, pVal, &rc);
} }
@ -3904,6 +3900,8 @@ int sessionChangesetConcat(
SessionTable *pList = 0; /* List of SessionTable objects */ SessionTable *pList = 0; /* List of SessionTable objects */
int rc; /* Return code */ int rc; /* Return code */
int bPatch; /* True for a patchset */ int bPatch; /* True for a patchset */
SessionTable *pTab;
SessionBuffer buf = {0, 0, 0};
assert( xOutput==0 || (ppOut==0 && pnOut==0) ); assert( xOutput==0 || (ppOut==0 && pnOut==0) );
@ -3916,41 +3914,37 @@ int sessionChangesetConcat(
/* Create the serialized output changeset based on the contents of the /* Create the serialized output changeset based on the contents of the
** hash tables attached to the SessionTable objects in list pList. ** hash tables attached to the SessionTable objects in list pList.
*/ */
if( rc==SQLITE_OK ){ for(pTab=pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
SessionTable *pTab; int i;
SessionBuffer buf = {0, 0, 0}; if( pTab->nEntry==0 ) continue;
for(pTab=pList; pTab && rc==SQLITE_OK; pTab=pTab->pNext){
int i;
if( pTab->nEntry==0 ) continue;
sessionAppendTableHdr(&buf, bPatch, pTab, &rc); sessionAppendTableHdr(&buf, bPatch, pTab, &rc);
for(i=0; i<pTab->nChange; i++){ for(i=0; i<pTab->nChange; i++){
SessionChange *p; SessionChange *p;
for(p=pTab->apChange[i]; p; p=p->pNext){ for(p=pTab->apChange[i]; p; p=p->pNext){
sessionAppendByte(&buf, p->op, &rc); sessionAppendByte(&buf, p->op, &rc);
sessionAppendByte(&buf, p->bIndirect, &rc); sessionAppendByte(&buf, p->bIndirect, &rc);
sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
}
}
if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){
rc = xOutput(pOut, buf.aBuf, buf.nBuf);
buf.nBuf = 0;
} }
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){
if( xOutput ){ rc = xOutput(pOut, buf.aBuf, buf.nBuf);
if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf); buf.nBuf = 0;
}else{
*ppOut = buf.aBuf;
*pnOut = buf.nBuf;
buf.aBuf = 0;
}
} }
sqlite3_free(buf.aBuf);
} }
if( rc==SQLITE_OK ){
if( xOutput ){
if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf);
}else{
*ppOut = buf.aBuf;
*pnOut = buf.nBuf;
buf.aBuf = 0;
}
}
sqlite3_free(buf.aBuf);
sessionDeleteTable(pList); sessionDeleteTable(pList);
return rc; return rc;
} }

View File

@ -75,7 +75,7 @@ struct TestSessionsBlob {
}; };
typedef struct TestSessionsBlob TestSessionsBlob; typedef struct TestSessionsBlob TestSessionsBlob;
static int testSessionsOutput( static int testStreamOutput(
void *pCtx, void *pCtx,
const void *pData, const void *pData,
int nData int nData
@ -160,9 +160,9 @@ static int test_session_cmd(
if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){ if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
void *pCtx = (void*)&o; void *pCtx = (void*)&o;
if( iSub==7 ){ if( iSub==7 ){
rc = sqlite3session_patchset_str(pSession, testSessionsOutput, pCtx); rc = sqlite3session_patchset_str(pSession, testStreamOutput, pCtx);
}else{ }else{
rc = sqlite3session_changeset_str(pSession, testSessionsOutput, pCtx); rc = sqlite3session_changeset_str(pSession, testStreamOutput, pCtx);
} }
}else{ }else{
if( iSub==7 ){ if( iSub==7 ){
@ -562,6 +562,13 @@ static int testStreamInput(
int nRem = p->nData - p->iData; /* Bytes of data available */ int nRem = p->nData - p->iData; /* Bytes of data available */
int nRet = p->nStream; /* Bytes actually returned */ int nRet = p->nStream; /* Bytes actually returned */
/* Allocate and free some space. There is no point to this, other than
** that it allows the regular OOM fault-injection tests to cause an error
** in this function. */
void *pAlloc = sqlite3_malloc(10);
if( pAlloc==0 ) return SQLITE_NOMEM;
sqlite3_free(pAlloc);
if( nRet>nReq ) nRet = nReq; if( nRet>nReq ) nRet = nReq;
if( nRet>nRem ) nRet = nRem; if( nRet>nRem ) nRet = nRem;
@ -691,7 +698,7 @@ static int test_sqlite3changeset_invert(
if( sIn.nStream ){ if( sIn.nStream ){
rc = sqlite3changeset_invert_str( rc = sqlite3changeset_invert_str(
testStreamInput, (void*)&sIn, testSessionsOutput, (void*)&sOut testStreamInput, (void*)&sIn, testStreamOutput, (void*)&sOut
); );
}else{ }else{
rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p); rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p);
@ -736,7 +743,7 @@ static int test_sqlite3changeset_concat(
rc = sqlite3changeset_concat_str( rc = sqlite3changeset_concat_str(
testStreamInput, (void*)&sLeft, testStreamInput, (void*)&sLeft,
testStreamInput, (void*)&sRight, testStreamInput, (void*)&sRight,
testSessionsOutput, (void*)&sOut testStreamOutput, (void*)&sOut
); );
}else{ }else{
rc = sqlite3changeset_concat( rc = sqlite3changeset_concat(

View File

@ -1,5 +1,5 @@
C Improve\ssessions\smodule\sdocumentation\sand\scomments.\sFix\ssome\sother\scode\sissues. C Fix\sa\ssegfault\sin\sthe\sstreaming\sAPI\sfunctions\striggered\sby\sa\svery\slong\stable\sname.
D 2014-09-27T12:26:18.848 D 2014-09-27T16:33:09.345
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -146,7 +146,7 @@ F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
F ext/session/session1.test 3733d71eb9a99b14d51fa5219d5b8a82407c3be8 F ext/session/session1.test 4653867f32a98ce4bbb4a181aac6debe51ca4dfb
F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b
F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01
F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84
@ -157,10 +157,10 @@ F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf
F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4
F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d
F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5
F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6 F ext/session/sessionfault.test cf9758bfb6ccd5db5f09f170667a8cea1ac8afa7
F ext/session/sqlite3session.c 9ce77f4752cd5d8982e7b64f665ae66754dda723 F ext/session/sqlite3session.c 228cca8fdb6fd07942be097c516f22e39ec39e3c
F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a
F ext/session/test_session.c 194083ee1f0f6f38404f662fe9b50849abd3b7ee F ext/session/test_session.c 56a4ddd443b571c8d365b03197c032bdaed1443a
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 4d8537eafb40e3687abc057ba26a1f7014f2c2d9 P bfc8bd80f8b225cebc66478448510ce84223ae7d
R c2c5a501f3f294cbca1bcb47eb806551 R 9ca53892e63f9c31475266a6b3e34d34
U dan U dan
Z c7ab4f2784fbdfc318b000ddf7671e24 Z f7759b84adfee5a6c178fa61db492ce5

View File

@ -1 +1 @@
bfc8bd80f8b225cebc66478448510ce84223ae7d d2642543eed54da1ac0f757d43dd4d72482eb752