From 56a83ef1b35fa18d525dbe95ed32e65c3eb0c338 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 27 Apr 2022 21:10:19 +0000 Subject: [PATCH] The -DSQLITE_MXFILENAMESZ=N option for some non-negative integer value N prevents SQLite from ever creating a hole larger than N bytes in a named file for which a size hint has been issued. The exception code never runs, except for cases when the application deliberately corrupts the size hint. FossilOrigin-Name: 0c2da4ff6434bc49afde117e27dc6cea31e2be333b8b5ddfb24f457ce1ef5db6 --- manifest | 15 +++++++++------ manifest.uuid | 2 +- src/os_unix.c | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 4b561cb6fc..79d2fb80a5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\stypo\sin\sa\scomment. -D 2022-04-27T18:38:46.859 +C The\s-DSQLITE_MXFILENAMESZ=N\soption\sfor\ssome\snon-negative\sinteger\svalue\sN\nprevents\sSQLite\sfrom\sever\screating\sa\shole\slarger\sthan\sN\sbytes\sin\sa\snamed\nfile\sfor\swhich\sa\ssize\shint\shas\sbeen\sissued.\s\sThe\sexception\scode\snever\nruns,\sexcept\sfor\scases\swhen\sthe\sapplication\sdeliberately\scorrupts\sthe\nsize\shint. +D 2022-04-27T21:10:19.508 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -537,7 +537,7 @@ F src/os.c b1c4f2d485961e9a5b6b648c36687d25047c252222e9660b7cc25a6e1ea436ab F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c 1f71ec8c87621f75c9c5ea973f5e8ce2f1d23fe760c01ed2814fe4b98b639825 +F src/os_unix.c e854f8de7c037ac0c85dcd324a1b275943ff62ae140773d52e8d75509a971eb0 F src/os_win.c a8ea80037e81127ca01959daa87387cc135f325c88dc745376c4f760de852a10 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 42120492784fc9bcd9082b5c9b5e329b7318c357f9f3574a1bbfcf7418910356 @@ -1951,8 +1951,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P eb59c46a5aed69bc6fd096997bf24c082e533c1085439f6ec1fbe5ff78e8b374 -R f499c3fddca86db7a0183d3ecdb0953b +P e1f4a115df34e45cf1bcf98961c699b582f564a58a979e95853b219bda06212c +R 5794d1298ad7cbc0b73b8c0832596e1c +T *branch * mkfileholesz +T *sym-mkfileholesz * +T -sym-trunk * U drh -Z 7426364b9684e9a6fe822d40fffa4b25 +Z 7def791b4ee1080fcb98c1f97ee1bab8 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1daa831936..c75aa9aa31 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e1f4a115df34e45cf1bcf98961c699b582f564a58a979e95853b219bda06212c \ No newline at end of file +0c2da4ff6434bc49afde117e27dc6cea31e2be333b8b5ddfb24f457ce1ef5db6 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 03ac3e46c9..7ff6fe851b 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -250,6 +250,9 @@ struct unixFile { #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif +#ifdef SQLITE_MXFILEHOLESZ + sqlite3_int64 sizeHint; /* Latest SQLITE_FCNTL_SIZE_HINT value */ +#endif #ifdef SQLITE_DEBUG /* The next group of variables are used to track whether or not the ** transaction counter in bytes 24-27 of database files are updated @@ -261,7 +264,6 @@ struct unixFile { unsigned char transCntrChng; /* True if the transaction counter changed */ unsigned char dbUpdate; /* True if any part of database file changed */ unsigned char inNormalWrite; /* True if in a normal write operation */ - #endif #ifdef SQLITE_TEST @@ -3456,6 +3458,35 @@ static int seekAndWriteFd( ** is set before returning. */ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ + +#ifdef SQLITE_MXFILEHOLESZ + /* If SQLite is compiled with -DSQLITE_MXFILEHOLESIZE=nnn for some + ** non-negative integer nnn, then the unix device driver will not allow + ** any writes to occur more than nnn bytes past the end of the most recent + ** SQLITE_FCNTL_SIZE_HINT, for named files that have ever received a size + ** hint. Unnamed files (which will be deleted when they are closed) are + ** not subject to this constraint. Also, journal files never receive + ** size hints, and so they are not restricted either. + ** + ** It is reasonable to set the MXFILEHOLESZ to zero. However, some of + ** the SQLite tests deliberately write holes (by accessing low-level + ** VFS routines directly) and so we need the ability to set a larger + ** MXFILEHOLESZ for testing purposes. + ** + ** This can be used as an extra security measure to prevent an error + ** from creating a file with a gargantuan hole that can go on to mess + ** up backup daemons that do not know how to deal with unix file holes. + ** + ** This option is off by default. It is undocumented. + */ + if( id->sizeHint>0 + && id->zPath!=0 + && offset>id->sizeHint+SQLITE_MXFILEHOLESZ + ){ + return SQLITE_IOERR_WRITE; + } +#endif /* SQLITE_MXFILEHOLESZ */ + return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno); } @@ -3990,8 +4021,11 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } case SQLITE_FCNTL_SIZE_HINT: { int rc; +#ifdef SQLITE_MXFILEHOLESZ + pFile->sizeHint = *(i64*)pArg; +#endif SimulateIOErrorBenign(1); - rc = fcntlSizeHint(pFile, *(i64 *)pArg); + rc = fcntlSizeHint(pFile, *(i64*)pArg); SimulateIOErrorBenign(0); return rc; } -- 2.47.2