]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a segfault in the streaming API functions triggered by a very long table name.
authordan <dan@noemail.net>
Sat, 27 Sep 2014 16:33:09 +0000 (16:33 +0000)
committerdan <dan@noemail.net>
Sat, 27 Sep 2014 16:33:09 +0000 (16:33 +0000)
FossilOrigin-Name: d2642543eed54da1ac0f757d43dd4d72482eb752

ext/session/session1.test
ext/session/sessionfault.test
ext/session/sqlite3session.c
ext/session/test_session.c
manifest
manifest.uuid

index e6f9c8fd7fdceff68fdcf1f3719b1ed69e926871..1c853a97a19e6b9001c86cc197c4066776a95075 100644 (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 {} {} {} {} {} {}}}}
 S delete
 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
index 4b278098a92dc6b9c6b4009a377a240a4aaf2a68..c94589e3729ec2c0488fe598d5e6306b294b77f9 100644 (file)
@@ -30,7 +30,6 @@ do_common_sql {
 faultsim_save_and_close
 db2 close
 
-
 #-------------------------------------------------------------------------
 # Test OOM error handling when collecting and applying a simple changeset.
 #
@@ -234,7 +233,7 @@ set changeset [changeset_from_sql {
 }]
 db close
 
-do_faultsim_test 5 -faults oom* -body {
+do_faultsim_test 5.1 -faults oom* -body {
   set ::inverse [sqlite3changeset_invert $::changeset]
   set {} {}
 } -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.
 #
index eb1ff1e7742dd9713afe7ae5ba5cc73af5609bb1..7e69be4cc4aacdd5fd7e021439ff01fa977860f1 100644 (file)
@@ -18,7 +18,7 @@ typedef struct SessionInput SessionInput;
 ** Minimum chunk size used by streaming versions of functions.
 */
 #ifdef SQLITE_TEST
-#define SESSIONS_STR_CHUNK_SIZE 1
+#define SESSIONS_STR_CHUNK_SIZE 64
 #else
 #define SESSIONS_STR_CHUNK_SIZE 1024
 #endif
@@ -1347,7 +1347,7 @@ static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){
   int rc = *pRc;
   if( rc==SQLITE_OK ){
     int nByte = 0;
-    sessionSerializeValue(0, pVal, &nByte);
+    rc = sessionSerializeValue(0, pVal, &nByte);
     sessionBufferGrow(p, nByte, &rc);
     if( rc==SQLITE_OK ){
       rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0);
@@ -2225,12 +2225,10 @@ static int sessionReadRecord(
       eType = pIn->aData[pIn->iNext++];
     }
 
-    assert( !apOut || apOut[i]==0 );
+    assert( apOut[i]==0 );
     if( eType ){
-      if( apOut ){
-        apOut[i] = sqlite3ValueNew(0);
-        if( !apOut[i] ) rc = SQLITE_NOMEM;
-      }
+      apOut[i] = sqlite3ValueNew(0);
+      if( !apOut[i] ) rc = SQLITE_NOMEM;
     }
 
     if( rc==SQLITE_OK ){
@@ -2239,22 +2237,20 @@ static int sessionReadRecord(
         int nByte;
         pIn->iNext += sessionVarintGet(aVal, &nByte);
         rc = sessionInputBuffer(pIn, nByte);
-        if( apOut && rc==SQLITE_OK ){
+        if( rc==SQLITE_OK ){
           u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
           rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
         }
         pIn->iNext += nByte;
       }
       if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
-        if( apOut ){
-          sqlite3_int64 v = sessionGetI64(aVal);
-          if( eType==SQLITE_INTEGER ){
-            sqlite3VdbeMemSetInt64(apOut[i], v);
-          }else{
-            double d;
-            memcpy(&d, &v, 8);
-            sqlite3VdbeMemSetDouble(apOut[i], d);
-          }
+        sqlite3_int64 v = sessionGetI64(aVal);
+        if( eType==SQLITE_INTEGER ){
+          sqlite3VdbeMemSetInt64(apOut[i], v);
+        }else{
+          double d;
+          memcpy(&d, &v, 8);
+          sqlite3VdbeMemSetDouble(apOut[i], d);
         }
         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] ){
       nRead++;
     }
-    if( pIn->aData[pIn->iNext + nRead]==0 ) break;
+    if( (pIn->iNext + nRead)<pIn->nData ) break;
     rc = sessionInputBuffer(pIn, nRead + 100);
   }
-  if( pnByte ) *pnByte = nRead+1;
+  *pnByte = nRead+1;
   return rc;
 }
 
@@ -2775,7 +2771,7 @@ static int sessionChangesetInvert(
         /* Write the new old.* record. Consists of the PK columns from the
         ** original old.* record, and the other values from the original
         ** 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)];
           sessionAppendValue(&sOut, pVal, &rc);
         }
@@ -2783,7 +2779,7 @@ static int sessionChangesetInvert(
         /* Write the new new.* record. Consists of a copy of all values
         ** from the original old.* record, except for the PK columns, which
         ** 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]);
           sessionAppendValue(&sOut, pVal, &rc);
         }
@@ -3904,6 +3900,8 @@ int sessionChangesetConcat(
   SessionTable *pList = 0;        /* List of SessionTable objects */
   int rc;                         /* Return code */
   int bPatch;                     /* True for a patchset */
+  SessionTable *pTab;
+  SessionBuffer buf = {0, 0, 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
   ** hash tables attached to the SessionTable objects in list pList. 
   */
-  if( rc==SQLITE_OK ){
-    SessionTable *pTab;
-    SessionBuffer buf = {0, 0, 0};
-    for(pTab=pList; pTab && rc==SQLITE_OK; pTab=pTab->pNext){
-      int i;
-      if( pTab->nEntry==0 ) continue;
-
-      sessionAppendTableHdr(&buf, bPatch, pTab, &rc);
-      for(i=0; i<pTab->nChange; i++){
-        SessionChange *p;
-        for(p=pTab->apChange[i]; p; p=p->pNext){
-          sessionAppendByte(&buf, p->op, &rc);
-          sessionAppendByte(&buf, p->bIndirect, &rc);
-          sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
-        }
-      }
+  for(pTab=pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
+    int i;
+    if( pTab->nEntry==0 ) continue;
 
-      if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){
-        rc = xOutput(pOut, buf.aBuf, buf.nBuf);
-        buf.nBuf = 0;
+    sessionAppendTableHdr(&buf, bPatch, pTab, &rc);
+    for(i=0; i<pTab->nChange; i++){
+      SessionChange *p;
+      for(p=pTab->apChange[i]; p; p=p->pNext){
+        sessionAppendByte(&buf, p->op, &rc);
+        sessionAppendByte(&buf, p->bIndirect, &rc);
+        sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
       }
     }
 
-    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;
-      }
+    if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STR_CHUNK_SIZE ){
+      rc = xOutput(pOut, buf.aBuf, buf.nBuf);
+      buf.nBuf = 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);
   return rc;
 }
index df690d44adbf81d6a634e9005c35d7d6affdaf9a..7e366ef3bb4178b48ff4297805c56eac96829f99 100644 (file)
@@ -75,7 +75,7 @@ struct TestSessionsBlob {
 };
 typedef struct TestSessionsBlob TestSessionsBlob;
 
-static int testSessionsOutput(
+static int testStreamOutput(
   void *pCtx,
   const void *pData,
   int nData
@@ -160,9 +160,9 @@ static int test_session_cmd(
       if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
         void *pCtx = (void*)&o;
         if( iSub==7 ){
-          rc = sqlite3session_patchset_str(pSession, testSessionsOutput, pCtx);
+          rc = sqlite3session_patchset_str(pSession, testStreamOutput, pCtx);
         }else{
-          rc = sqlite3session_changeset_str(pSession, testSessionsOutput, pCtx);
+          rc = sqlite3session_changeset_str(pSession, testStreamOutput, pCtx);
         }
       }else{
         if( iSub==7 ){
@@ -562,6 +562,13 @@ static int testStreamInput(
   int nRem = p->nData - p->iData; /* Bytes of data available */
   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>nRem ) nRet = nRem;
 
@@ -691,7 +698,7 @@ static int test_sqlite3changeset_invert(
 
   if( sIn.nStream ){
     rc = sqlite3changeset_invert_str(
-        testStreamInput, (void*)&sIn, testSessionsOutput, (void*)&sOut
+        testStreamInput, (void*)&sIn, testStreamOutput, (void*)&sOut
     );
   }else{
     rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p);
@@ -736,7 +743,7 @@ static int test_sqlite3changeset_concat(
     rc = sqlite3changeset_concat_str(
         testStreamInput, (void*)&sLeft,
         testStreamInput, (void*)&sRight,
-        testSessionsOutput, (void*)&sOut
+        testStreamOutput, (void*)&sOut
     );
   }else{
     rc = sqlite3changeset_concat(
index 258fb598ba6f09f371d31d0385fab0a9fb97c28e..4cb1bee75c411995d5eea11f4ef08dc992230cd8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Improve\ssessions\smodule\sdocumentation\sand\scomments.\sFix\ssome\sother\scode\sissues.
-D 2014-09-27T12:26:18.848
+C Fix\sa\ssegfault\sin\sthe\sstreaming\sAPI\sfunctions\striggered\sby\sa\svery\slong\stable\sname.
+D 2014-09-27T16:33:09.345
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -146,7 +146,7 @@ F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
 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/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01
 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/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d
 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5
-F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6
-F ext/session/sqlite3session.c 9ce77f4752cd5d8982e7b64f665ae66754dda723
+F ext/session/sessionfault.test cf9758bfb6ccd5db5f09f170667a8cea1ac8afa7
+F ext/session/sqlite3session.c 228cca8fdb6fd07942be097c516f22e39ec39e3c
 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/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 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.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 4d8537eafb40e3687abc057ba26a1f7014f2c2d9
-R c2c5a501f3f294cbca1bcb47eb806551
+P bfc8bd80f8b225cebc66478448510ce84223ae7d
+R 9ca53892e63f9c31475266a6b3e34d34
 U dan
-Z c7ab4f2784fbdfc318b000ddf7671e24
+Z f7759b84adfee5a6c178fa61db492ce5
index 31da46d10be16c7e61a6ad16eeb9ca5a58ccccd5..903686ec1f7c5c3bcfd4ea57f9dadd2395b6ef47 100644 (file)
@@ -1 +1 @@
-bfc8bd80f8b225cebc66478448510ce84223ae7d
\ No newline at end of file
+d2642543eed54da1ac0f757d43dd4d72482eb752
\ No newline at end of file