]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Revise the layout of filenames in the Pager object so that it is unchanged
authordrh <drh@noemail.net>
Mon, 27 Jan 2020 14:40:44 +0000 (14:40 +0000)
committerdrh <drh@noemail.net>
Mon, 27 Jan 2020 14:40:44 +0000 (14:40 +0000)
from prior versions.  It turns out that some important 3rd-party software
does questionable pointer manipulations on those filenames that depend on
that legacy layout.  Technical this is a misuse of SQLite by the 3rd-party
software, but we want to avoid unnecessary breakage.

FossilOrigin-Name: 34ab760689fd493eda482e856047708d74e769a01cc90b69da456d79ffe39aea

manifest
manifest.uuid
src/main.c
src/pager.c

index b3af23952d87646e53674c0cc019a1b6d4d0dcab..37b823b7ecdc79135233059ed65fb6538f3220b3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\stypos\sin\sthe\ssqlite3ext.h\sheader\sfile\sthat\sprevent\ssome\snewer\sAPIs\sfrom\nbeing\saccessed\sfrom\sloadable\sextensions.
-D 2020-01-23T15:00:18.610
+C Revise\sthe\slayout\sof\sfilenames\sin\sthe\sPager\sobject\sso\sthat\sit\sis\sunchanged\nfrom\sprior\sversions.\s\sIt\sturns\sout\sthat\ssome\simportant\s3rd-party\ssoftware\ndoes\squestionable\spointer\smanipulations\son\sthose\sfilenames\sthat\sdepend\son\nthat\slegacy\slayout.\s\sTechnical\sthis\sis\sa\smisuse\sof\sSQLite\sby\sthe\s3rd-party\nsoftware,\sbut\swe\swant\sto\savoid\sunnecessary\sbreakage.
+D 2020-01-27T14:40:44.978
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -495,7 +495,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 2fe4d7f67078a68650f16e4efe73207899e21702e6b9d2e8ad1894c76dcad352
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 8cd803f1747c03a50b32fe87ebfb5851998d0cdafefe02737daa95e0616b42bb
-F src/main.c 430db07f140a2455784b504af1a56fe49134a79dd479a203370490031708d48f
+F src/main.c ffaa1308ee8ad7cf70bddc9a9fe2d2d66799e534b12ec876562d26a33a30d745
 F src/malloc.c eaa4dc9602ce28b077f7de2eb275db2be270c5cc56d7fec5466301bd9b80e2f5
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -518,7 +518,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
 F src/os_unix.c ad7640c04eed946052a3b12856362a773d0a717696707313037186df0e2b59f2
 F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 302a18da8b247881808cd65009e1ac7c8b6e5cefb22ed9a1c330ed47b73e94ab
+F src/pager.c c0bca72aa3f7b1cf521a9f350fcf8e5975ebf98da7dbb03492be876b0f053781
 F src/pager.h 71fe1d5016ec54d0cc5d344cd474e563450b438c59f535e8c1ec8a13b1373f14
 F src/parse.y c8d2de64db469fd56e0fa24da46cd8ec8523eb98626567d2708df371b47fdc3f
 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
@@ -1857,7 +1857,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8a6fe3066cf0599fcf2960e8fb3ae39e4e7a61ec81e8ec71d0b5910aee2c16f6
-R adbf99f7d511d2f7862e65bcc9604066
+P 14331989fcaf6591336290ed1548e9c90f0f153e27f456f4c30c966f9c23aa6e
+R 883ff2472492f888f089aeac00d37048
 U drh
-Z 72d824d23352153c482aa4a2ca7c7d22
+Z 470802efe5cd145ed0af48cfd87c7792
index d36bb65850aca7d5f4adac089d5531d9d2357a38..837e4d4b16c393614ee86543004f7bfd22f6b36d 100644 (file)
@@ -1 +1 @@
-14331989fcaf6591336290ed1548e9c90f0f153e27f456f4c30c966f9c23aa6e
\ No newline at end of file
+34ab760689fd493eda482e856047708d74e769a01cc90b69da456d79ffe39aea
\ No newline at end of file
index 903f187a9f2958a04aa217328bcf5d13aadbe9c4..3983f083b23ab40ec45bea75c7d06fb9cdaa14e8 100644 (file)
@@ -4243,6 +4243,21 @@ int sqlite3_test_control(int op, ...){
   return rc;
 }
 
+/*
+** The Pager stores the Database filename, Journal filename, and WAL filename
+** consecutively in memory, in that order.  The database filename is prefixed
+** by four zero bytes.  Locate the start of the database filename by searching
+** backwards for the first byte following four consecutive zero bytes.
+**
+** This only works if the filename passed in was obtained from the Pager.
+*/
+static const char *databaseName(const char *zName){
+  while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
+    zName--;
+  }
+  return zName;
+}
+
 /*
 ** This is a utility routine, useful to VFS implementations, that checks
 ** to see if a database file was a URI that contained a specific query 
@@ -4256,6 +4271,7 @@ int sqlite3_test_control(int op, ...){
 */
 const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
   if( zFilename==0 || zParam==0 ) return 0;
+  zFilename = databaseName(zFilename);
   zFilename += sqlite3Strlen30(zFilename) + 1;
   while( zFilename[0] ){
     int x = strcmp(zFilename, zParam);
@@ -4271,6 +4287,7 @@ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
 */
 const char *sqlite3_uri_key(const char *zFilename, int N){
   if( zFilename==0 || N<0 ) return 0;
+  zFilename = databaseName(zFilename);
   zFilename += sqlite3Strlen30(zFilename) + 1;
   while( zFilename[0] && (N--)>0 ){
     zFilename += sqlite3Strlen30(zFilename) + 1;
@@ -4304,25 +4321,6 @@ sqlite3_int64 sqlite3_uri_int64(
   return bDflt;
 }
 
-/*
-** The Pager stores the Journal filename, WAL filename, and Database filename
-** consecutively in memory, in that order, with prefixes \000\001\000,
-** \002\000, and \003\000, in that order.  Thus the three names look like query
-** parameters if you start at the first prefix.
-**
-** This routine backs up a filename to the start of the first prefix.
-**
-** This only works if the filenamed passed in was obtained from the Pager.
-*/
-static const char *startOfNameList(const char *zName){
-  while( zName[0]!='\001' || zName[1]!=0 ){
-    zName -= 3;
-    while( zName[0]!='\000' ){ zName--; }
-    zName++;
-  }
-  return zName-1;
-}
-
 /*
 ** Translate a filename that was handed to a VFS routine into the corresponding
 ** database, journal, or WAL file.
@@ -4334,14 +4332,26 @@ static const char *startOfNameList(const char *zName){
 ** corruption.
 */
 const char *sqlite3_filename_database(const char *zFilename){
+  return databaseName(zFilename);
   return sqlite3_uri_parameter(zFilename - 3, "\003");
 }
 const char *sqlite3_filename_journal(const char *zFilename){
-  const char *z = sqlite3_uri_parameter(startOfNameList(zFilename), "\001");
-  return ALWAYS(z) && z[0] ? z : 0;
+  zFilename = databaseName(zFilename);
+  zFilename += sqlite3Strlen30(zFilename) + 1;
+  while( zFilename[0] ){
+    zFilename += sqlite3Strlen30(zFilename) + 1;
+    zFilename += sqlite3Strlen30(zFilename) + 1;
+  }
+  return zFilename + 1;
 }
 const char *sqlite3_filename_wal(const char *zFilename){
-  return sqlite3_uri_parameter(startOfNameList(zFilename), "\002");
+#ifdef SQLITE_OMIT_WAL
+  return 0;
+#else
+  zFilename = sqlite3_filename_journal(zFilename);
+  zFilename += sqlite3Strlen30(zFilename) + 1;
+  return zFilename;
+#endif
 }
 
 /*
index ae75aeb7cf342ba5c89eeded612c8fe1a1507685..66cee1f186705bf1350ada0383e952807285710c 100644 (file)
@@ -4838,30 +4838,48 @@ int sqlite3PagerOpen(
   **     Database file handle            (pVfs->szOsFile bytes)
   **     Sub-journal file handle         (journalFileSize bytes)
   **     Main journal file handle        (journalFileSize bytes)
-  **     \0\1\0 journal prefix           (3 bytes)
-  **     Journal filename                (nPathname+8+1 bytes)
-  **     \2\0 WAL prefix                 (2 bytes)
-  **     WAL filename                    (nPathname+4+1 bytes)
-  **     \3\0 database prefix            (2 bytes)
+  **     \0\0\0\0 database prefix        (4 bytes)
   **     Database file name              (nPathname+1 bytes)
   **     URI query parameters            (nUriByte bytes)
-  **     \0\0 terminator                 (2 bytes)
+  **     Journal filename                (nPathname+8+1 bytes)
+  **     WAL filename                    (nPathname+4+1 bytes)
+  **     \0\0\0 terminator               (3 bytes)
+  **
+  ** Some 3rd-party software, over which we have no control, depends on
+  ** the specific order of the filenames and the \0 separators between them
+  ** so that it can (for example) find the database filename given the WAL
+  ** filename without using the sqlite3_filename_database() API.  This is a
+  ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
+  ** software is in widespread use, so we try to avoid changing the filename
+  ** order and formatting if possible.  In particular, the details of the
+  ** filename format expected by 3rd-party software should be as follows:
+  **
+  **   - Main Database Path
+  **   - \0
+  **   - Multiple URI components consisting of:
+  **     - Key
+  **     - \0
+  **     - Value
+  **     - \0
+  **   - \0
+  **   - Journal Path
+  **   - \0
+  **   - WAL Path (zWALName)
+  **   - \0
   */
   pPtr = (u8 *)sqlite3MallocZero(
     ROUND8(sizeof(*pPager)) +            /* Pager structure */
     ROUND8(pcacheSize) +                 /* PCache object */
     ROUND8(pVfs->szOsFile) +             /* The main db file */
     journalFileSize * 2 +                /* The two journal files */
-    3 +                                  /* Journal prefix */
+    4 +                                  /* Database prefix */
+    nPathname + 1 +                      /* database filename */
+    nUriByte +                           /* query parameters */
     nPathname + 8 + 1 +                  /* Journal filename */
 #ifndef SQLITE_OMIT_WAL
-    2 +                                  /* WAL prefix */
     nPathname + 4 + 1 +                  /* WAL filename */
 #endif
-    2 +                                  /* Database prefix */
-    nPathname + 1 +                      /* database filename */
-    nUriByte +                           /* query parameters */
-    2                                    /* Terminator */
+    3                                    /* Terminator */
   );
   assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
   if( !pPtr ){
@@ -4875,9 +4893,20 @@ int sqlite3PagerOpen(
   pPager->jfd =  (sqlite3_file*)pPtr;     pPtr += journalFileSize;
   assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
 
+  /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
+                                          pPtr += 4;  /* Skip zero prefix */
+  pPager->zFilename = (char*)pPtr;
+  if( nPathname>0 ){
+    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname + 1;
+    if( zUri ){
+      memcpy(pPtr, zUri, nUriByte);       pPtr += nUriByte;
+    }else{
+                                          pPtr++;
+    }
+  }
+
 
   /* Fill in Pager.zJournal */
-  pPtr[1] = '\001';                       pPtr += 3;
   if( nPathname>0 ){
     pPager->zJournal = (char*)pPtr;
     memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname;
@@ -4888,12 +4917,10 @@ int sqlite3PagerOpen(
 #endif
   }else{
     pPager->zJournal = 0;
-    pPtr++;
   }
 
 #ifndef SQLITE_OMIT_WAL
   /* Fill in Pager.zWal */
-  pPtr[0] = '\002'; pPtr[1] = 0;          pPtr += 2;
   if( nPathname>0 ){
     pPager->zWal = (char*)pPtr;
     memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname;
@@ -4904,21 +4931,9 @@ int sqlite3PagerOpen(
 #endif
   }else{
     pPager->zWal = 0;
-    pPtr++;
   }
 #endif
 
-  /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
-  pPtr[0] = '\003'; pPtr[1] = 0;          pPtr += 2;
-  pPager->zFilename = (char*)pPtr;
-  if( nPathname>0 ){
-    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname + 1;
-    if( zUri ){
-      memcpy(pPtr, zUri, nUriByte);    /* pPtr += nUriByte; // not needed */
-    }
-    /* Double-zero terminator implied by the sqlite3MallocZero */
-  }
-
   if( nPathname ) sqlite3DbFree(0, zPathname);
   pPager->pVfs = pVfs;
   pPager->vfsFlags = vfsFlags;
@@ -7038,8 +7053,8 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
 ** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
 */
 const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
-  static const char zFake[] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
-  return (nullIfMemDb && pPager->memDb) ? &zFake[3] : pPager->zFilename;
+  static const char zFake[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+  return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename;
 }
 
 /*