]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Backport support for the sqlite3_hard_heap_limit64() interface and the
authordrh <drh@noemail.net>
Thu, 14 Nov 2019 23:08:00 +0000 (23:08 +0000)
committerdrh <drh@noemail.net>
Thu, 14 Nov 2019 23:08:00 +0000 (23:08 +0000)
hard_heap_limit pragma to the 3.30 branch.

FossilOrigin-Name: ba27012d43a84e22a8329adfe8284e4299432a373e6cb0c6e9e1e20a1b543436

14 files changed:
manifest
manifest.uuid
src/loadext.c
src/malloc.c
src/pragma.c
src/pragma.h
src/sqlite.h.in
src/sqlite3ext.h
src/test1.c
src/treeview.c
test/fuzzcheck.c
test/ossfuzz.c
test/tester.tcl
tool/mkpragmatab.tcl

index 1cff7b7b8568c34050bc8d4cc9e2e81aa01ea0c2..6061c085f79c2701f9d48bb6d8814442ef39f269 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Version\s3.30.1
-D 2019-10-10T20:19:45.339
+C Backport\ssupport\sfor\sthe\ssqlite3_hard_heap_limit64()\sinterface\sand\sthe\nhard_heap_limit\spragma\sto\sthe\s3.30\sbranch.
+D 2019-11-14T23:08:00.676
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -488,9 +488,9 @@ F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 40557ebd69f4115e7a273f9304a8ab637a47ce44f3c6923396928f023967b5e8
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
-F src/loadext.c 4ddc65ae13c0d93db0ceedc8b14a28c8c260513448b0eb8c5a2ac375e3b6a85d
+F src/loadext.c d74f5e7bd51f3c9d283442473eb65aef359664efd6513591c03f01881c4ae2da
 F src/main.c 3851950717170ade4f6d718c18c6c7400ef5994c2a654679af2cff2ffd0fb2b9
-F src/malloc.c 0f9da2a66b230a5785af94b9672126845099b57b70a32c987d04ac28c69da990
+F src/malloc.c b5acd8b5e04054dd2792d67cab8f7d88564cd9d11015e082c9880fada5be386a
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
 F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -518,8 +518,8 @@ F src/parse.y 50bfcb34be7320dd0cb875021a93ae6451c8f0b083f21b71934a1a3a9108015a
 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
 F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848
-F src/pragma.c b47bc7db02ab13d04c680aee424466b4e34f4ef5aa7b2e464876ec005806f98f
-F src/pragma.h 40962d65b645bb3f08c1f4c456effd01c6e7f073f68ea25177e0c95e181cff75
+F src/pragma.c 6bad15da51a015118e4ed259a103131b29b0fe6bab004bd9c3b8588288b96c12
+F src/pragma.h 885f2f5da85848278fa2240c47539e21a58291d7a53bbb50e8df00d208d48d97
 F src/prepare.c 132484635a30f873ee7eccd47f93ed1932503863b93b28423b42332d81adffaf
 F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
@@ -527,15 +527,15 @@ F src/resolve.c e021be0c1c4a2125fa38aabcd8dbb764bf5b2c889a948c30d3708430ec6ccd00
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
 F src/select.c b3d64a7a3342471ce078251c5ba132f8ec66f994534f1070dda025b354a09a62
 F src/shell.c.in d70bcf630c4073eaa994fa74be98886c781918e794cb8b562be8df10f018e274
-F src/sqlite.h.in 5725a6b20190a1e8d662077a1c1c8ea889ad7be90dd803f914c2de226f5fe6ab
+F src/sqlite.h.in d568986ef8d8c89e8cd89e234899f25a52068e0daa919dcf3565f9dcef92b3cd
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31
+F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
 F src/sqliteInt.h b8cabe8fcef93b7251422db41903c04abb4052df015eacb886dabd496fc3e0e8
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
 F src/tclsqlite.c 50c93be3e1c03b4e6cf6756e5197afcfe7f5cd0497d83a7ac317cde09e19b290
-F src/test1.c 17e1395cbddeb9226b756d723a7566b45b43b99a5f9f55afb4ff70888de6ad6f
+F src/test1.c c727c44a122c8a86b7d673dd4f20adae49f8426efcf866091d3415677db4c11b
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
 F src/test4.c 405834f6a93ec395cc4c9bb8ecebf7c3d8079e7ca16ae65e82d01afd229694bb
@@ -590,7 +590,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e
-F src/treeview.c fddeb413159c3eeeaea3f496172f121cf3695606c461dc4e6dcee51417952df5
+F src/treeview.c dd7efb04c28edf4bec1c70f97bc2258c45e6f81006085d74ca2db0d5b8d9bb9a
 F src/trigger.c 845ccc08f60716c58aa28fe6470385c18ef8c4e1d88c93dcf449bc13d464eb2e
 F src/update.c 7f05fad5e145248a00048aeb0bac78b8fdb4ed17216e14a6eb24c55596e87ee7
 F src/upsert.c 710c91bb13e3c3fed5b6fe17cb13e09560bdd003ad8b8c51e6b16c80cfc48b10
@@ -1007,7 +1007,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
 F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
 F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c 3ad76298a80cda31d270dc5e4f31194fa38d507d3e9b3f355cf1c283895cd5a5
+F test/fuzzcheck.c e8cf694f71a1ee39a59f7c2a38c0f8660db0656ce47c8a334b6e9a11f1e66c6d
 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
 F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1205,7 +1205,7 @@ F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
 F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
 F test/orderbyA.test df608e59efc2ef50c1eddf1a773b272de3252e9401bfec86d04b52fd973866d5
 F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6abbc5
-F test/ossfuzz.c 18af635fa73d12a109b305faca727a734c1fa28a421b161d9d15c5a84a4998a2
+F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d71096715
 F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
 F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
 F test/pager1.test 1e9ee778bdeaf4f7f09997d029cdaca6a42dfc2092edafe4f5e590acbf1eab13
@@ -1402,7 +1402,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
 F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
 F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
 F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl 64ac253a411db1af7649438f674213a45876ca70609570310a8652edf23e5d77
+F test/tester.tcl abba168acd7f01dbfa3ffdbf402d151eb97e8a824d9208e845ab34c194441483
 F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1779,7 +1779,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6
 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
 F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
-F tool/mkpragmatab.tcl f115d63ada8171f9da28dc8e34e043a1a159692d46b89f66b6e681140bc4683d
+F tool/mkpragmatab.tcl 3ee0d8cfbf78c5b427709ce94cbb9aa5c8d4a678522e981a082e30c19d2dffab
 F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1846,10 +1846,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c6cc2390e91097a32992d11c74af8e77a6a42862ec8a936b549e156250629407
-R 9b77b3da995b6a235a01d1e768df1101
-T +bgcolor * #d0c0ff
-T +sym-release *
-T +sym-version-3.30.1 *
+P 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b
+Q +6399c47ea89c5766274bd6abdc9b6a85fe5b7f6c1078972c2f58e624bae59b7c
+R 0540f61436f821c83da2a74759ecb87d
 U drh
-Z 6b715002b9e76fa6c3cf0c09f9813287
+Z 26c9aedefe3af9bc6beda85fa9ab28af
index 67ff2f9e3eb53ab3001a86fea30df71085524dde..a5df1a1d51b03df8254774685865e8e3b4f850ec 100644 (file)
@@ -1 +1 @@
-18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b
\ No newline at end of file
+ba27012d43a84e22a8329adfe8284e4299432a373e6cb0c6e9e1e20a1b543436
\ No newline at end of file
index 423a16fde9dcc5b59052d432e3e4cc83e38be85e..2622a81711f1a9c5a94bbef90d32ec01e6289e18 100644 (file)
@@ -468,6 +468,8 @@ static const sqlite3_api_routines sqlite3Apis = {
 #else
   0,
 #endif
+  /* Version 3.31.0 and later */
+  sqlite3_hard_heap_limit64,
 };
 
 /*
index 559e7259cee7bca2e4bc6b6b90886eb6b99e660a..57fa65215586fab7d43ab87238e3f6fa5a0c0ada 100644 (file)
@@ -32,19 +32,27 @@ int sqlite3_release_memory(int n){
 #endif
 }
 
+/*
+** Default value of the hard heap limit.  0 means "no limit".
+*/
+#ifndef SQLITE_MAX_MEMORY
+# define SQLITE_MAX_MEMORY 0
+#endif
+
 /*
 ** State information local to the memory allocation subsystem.
 */
 static SQLITE_WSD struct Mem0Global {
   sqlite3_mutex *mutex;         /* Mutex to serialize access */
   sqlite3_int64 alarmThreshold; /* The soft heap limit */
+  sqlite3_int64 hardLimit;      /* The hard upper bound on memory */
 
   /*
   ** True if heap is nearly "full" where "full" is defined by the
   ** sqlite3_soft_heap_limit() setting.
   */
   int nearlyFull;
-} mem0 = { 0, 0, 0 };
+} mem0 = { 0, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 };
 
 #define mem0 GLOBAL(struct Mem0Global, mem0)
 
@@ -74,8 +82,15 @@ int sqlite3_memory_alarm(
 #endif
 
 /*
-** Set the soft heap-size limit for the library. Passing a zero or 
-** negative value indicates no limit.
+** Set the soft heap-size limit for the library.  An argument of
+** zero disables the limit.  A negative argument is a no-op used to
+** obtain the return value.
+**
+** The return value is the value of the heap limit just before this
+** interface was called.
+**
+** If the hard heap limit is enabled, then the soft heap limit cannot
+** be disabled nor raised above the hard heap limit.
 */
 sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
   sqlite3_int64 priorLimit;
@@ -91,6 +106,9 @@ sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
     sqlite3_mutex_leave(mem0.mutex);
     return priorLimit;
   }
+  if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
+    n = mem0.hardLimit;
+  }
   mem0.alarmThreshold = n;
   nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
   mem0.nearlyFull = (n>0 && n<=nUsed);
@@ -104,6 +122,37 @@ void sqlite3_soft_heap_limit(int n){
   sqlite3_soft_heap_limit64(n);
 }
 
+/*
+** Set the hard heap-size limit for the library. An argument of zero
+** disables the hard heap limit.  A negative argument is a no-op used
+** to obtain the return value without affecting the hard heap limit.
+**
+** The return value is the value of the hard heap limit just prior to
+** calling this interface.
+**
+** Setting the hard heap limit will also activate the soft heap limit
+** and constrain the soft heap limit to be no more than the hard heap
+** limit.
+*/
+sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){
+  sqlite3_int64 priorLimit;
+#ifndef SQLITE_OMIT_AUTOINIT
+  int rc = sqlite3_initialize();
+  if( rc ) return -1;
+#endif
+  sqlite3_mutex_enter(mem0.mutex);
+  priorLimit = mem0.hardLimit;
+  if( n>=0 ){
+    mem0.hardLimit = n;
+    if( n<mem0.alarmThreshold || mem0.alarmThreshold==0 ){
+      mem0.alarmThreshold = n;
+    }
+  }
+  sqlite3_mutex_leave(mem0.mutex);
+  return priorLimit;
+}
+
+
 /*
 ** Initialize the memory allocation subsystem.
 */
@@ -190,19 +239,19 @@ static void mallocWithAlarm(int n, void **pp){
   ** following xRoundup() call. */
   nFull = sqlite3GlobalConfig.m.xRoundup(n);
 
-#ifdef SQLITE_MAX_MEMORY
-  if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
-    *pp = 0;
-    return;
-  }
-#endif
-
   sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
   if( mem0.alarmThreshold>0 ){
     sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
     if( nUsed >= mem0.alarmThreshold - nFull ){
       mem0.nearlyFull = 1;
       sqlite3MallocAlarm(nFull);
+      if( mem0.hardLimit ){
+        nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+        if( nUsed >= mem0.hardLimit - nFull ){
+          *pp = 0;
+          return;
+        }
+      }
     }else{
       mem0.nearlyFull = 0;
     }
index 858e314a1e1b61606546099caeae667ca062b688..2dec6634e99338728ca549276a8b907f84e22810 100644 (file)
@@ -2080,6 +2080,27 @@ void sqlite3Pragma(
     break;
   }
 
+  /*
+  **   PRAGMA hard_heap_limit
+  **   PRAGMA hard_heap_limit = N
+  **
+  ** Invoke sqlite3_hard_heap_limit64() to query or set the hard heap
+  ** limit.  The hard heap limit can be activated or lowered by this
+  ** pragma, but not raised or deactivated.  Only the
+  ** sqlite3_hard_heap_limit64() C-language API can raise or deactivate
+  ** the hard heap limit.  This allows an application to set a heap limit
+  ** constraint that cannot be relaxed by an untrusted SQL script.
+  */
+  case PragTyp_HARD_HEAP_LIMIT: {
+    sqlite3_int64 N;
+    if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
+      sqlite3_int64 iPrior = sqlite3_hard_heap_limit64(-1);
+      if( N>0 && (iPrior==0 || iPrior>N) ) sqlite3_hard_heap_limit64(N);
+    }
+    returnSingleInt(v, sqlite3_hard_heap_limit64(-1));
+    break;
+  }
+
   /*
   **   PRAGMA threads
   **   PRAGMA threads = N
index b7f3282ded6b43d64435a38bbb3b9f9b4114057c..66bfcf74794816636ccd26b66e5425ee5ee705cc 100644 (file)
 #define PragTyp_FOREIGN_KEY_CHECK             13
 #define PragTyp_FOREIGN_KEY_LIST              14
 #define PragTyp_FUNCTION_LIST                 15
-#define PragTyp_INCREMENTAL_VACUUM            16
-#define PragTyp_INDEX_INFO                    17
-#define PragTyp_INDEX_LIST                    18
-#define PragTyp_INTEGRITY_CHECK               19
-#define PragTyp_JOURNAL_MODE                  20
-#define PragTyp_JOURNAL_SIZE_LIMIT            21
-#define PragTyp_LOCK_PROXY_FILE               22
-#define PragTyp_LOCKING_MODE                  23
-#define PragTyp_PAGE_COUNT                    24
-#define PragTyp_MMAP_SIZE                     25
-#define PragTyp_MODULE_LIST                   26
-#define PragTyp_OPTIMIZE                      27
-#define PragTyp_PAGE_SIZE                     28
-#define PragTyp_PRAGMA_LIST                   29
-#define PragTyp_SECURE_DELETE                 30
-#define PragTyp_SHRINK_MEMORY                 31
-#define PragTyp_SOFT_HEAP_LIMIT               32
-#define PragTyp_SYNCHRONOUS                   33
-#define PragTyp_TABLE_INFO                    34
-#define PragTyp_TEMP_STORE                    35
-#define PragTyp_TEMP_STORE_DIRECTORY          36
-#define PragTyp_THREADS                       37
-#define PragTyp_WAL_AUTOCHECKPOINT            38
-#define PragTyp_WAL_CHECKPOINT                39
-#define PragTyp_ACTIVATE_EXTENSIONS           40
-#define PragTyp_KEY                           41
-#define PragTyp_LOCK_STATUS                   42
-#define PragTyp_STATS                         43
+#define PragTyp_HARD_HEAP_LIMIT               16
+#define PragTyp_INCREMENTAL_VACUUM            17
+#define PragTyp_INDEX_INFO                    18
+#define PragTyp_INDEX_LIST                    19
+#define PragTyp_INTEGRITY_CHECK               20
+#define PragTyp_JOURNAL_MODE                  21
+#define PragTyp_JOURNAL_SIZE_LIMIT            22
+#define PragTyp_LOCK_PROXY_FILE               23
+#define PragTyp_LOCKING_MODE                  24
+#define PragTyp_PAGE_COUNT                    25
+#define PragTyp_MMAP_SIZE                     26
+#define PragTyp_MODULE_LIST                   27
+#define PragTyp_OPTIMIZE                      28
+#define PragTyp_PAGE_SIZE                     29
+#define PragTyp_PRAGMA_LIST                   30
+#define PragTyp_SECURE_DELETE                 31
+#define PragTyp_SHRINK_MEMORY                 32
+#define PragTyp_SOFT_HEAP_LIMIT               33
+#define PragTyp_SYNCHRONOUS                   34
+#define PragTyp_TABLE_INFO                    35
+#define PragTyp_TEMP_STORE                    36
+#define PragTyp_TEMP_STORE_DIRECTORY          37
+#define PragTyp_THREADS                       38
+#define PragTyp_WAL_AUTOCHECKPOINT            39
+#define PragTyp_WAL_CHECKPOINT                40
+#define PragTyp_ACTIVATE_EXTENSIONS           41
+#define PragTyp_KEY                           42
+#define PragTyp_LOCK_STATUS                   43
+#define PragTyp_STATS                         44
 
 /* Property flags associated with various pragma. */
 #define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -319,6 +320,11 @@ static const PragmaName aPragmaName[] = {
   /* iArg:      */ 0 },
 #endif
 #endif
+ {/* zName:     */ "hard_heap_limit",
+  /* ePragTyp:  */ PragTyp_HARD_HEAP_LIMIT,
+  /* ePragFlg:  */ PragFlg_Result0,
+  /* ColNames:  */ 0, 0,
+  /* iArg:      */ 0 },
 #if defined(SQLITE_HAS_CODEC)
  {/* zName:     */ "hexkey",
   /* ePragTyp:  */ PragTyp_KEY,
index 9dbc80764f4c140d91b147cbb9b3a018e70a07e2..c9e880a43d8ac9ec6873879e6d7792bb02b26d76 100644 (file)
@@ -1742,6 +1742,7 @@ struct sqlite3_mem_methods {
 ** memory allocation statistics. ^(When memory allocation statistics are
 ** disabled, the following SQLite interfaces become non-operational:
 **   <ul>
+**   <li> [sqlite3_hard_heap_limit64()]
 **   <li> [sqlite3_memory_used()]
 **   <li> [sqlite3_memory_highwater()]
 **   <li> [sqlite3_soft_heap_limit64()]
@@ -6116,6 +6117,9 @@ int sqlite3_db_release_memory(sqlite3*);
 /*
 ** CAPI3REF: Impose A Limit On Heap Size
 **
+** These interfaces impose limits on the amount of heap memory that will be
+** by all database connections within a single process.
+**
 ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
 ** soft limit on the amount of heap memory that may be allocated by SQLite.
 ** ^SQLite strives to keep heap memory utilization below the soft heap
@@ -6126,20 +6130,41 @@ int sqlite3_db_release_memory(sqlite3*);
 ** an [SQLITE_NOMEM] error.  In other words, the soft heap limit 
 ** is advisory only.
 **
-** ^The return value from sqlite3_soft_heap_limit64() is the size of
-** the soft heap limit prior to the call, or negative in the case of an
-** error.  ^If the argument N is negative
-** then no change is made to the soft heap limit.  Hence, the current
-** size of the soft heap limit can be determined by invoking
-** sqlite3_soft_heap_limit64() with a negative argument.
-**
-** ^If the argument N is zero then the soft heap limit is disabled.
+** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
+** N bytes on the amount of memory that will be allocated.  ^The
+** sqlite3_hard_heap_limit64(N) interface is similar to
+** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
+** when the hard heap limit is reached.
 **
-** ^(The soft heap limit is not enforced in the current implementation
+** ^The return value from both sqlite3_soft_heap_limit64() and
+** sqlite3_hard_heap_limit64() is the size of
+** the heap limit prior to the call, or negative in the case of an
+** error.  ^If the argument N is negative
+** then no change is made to the heap limit.  Hence, the current
+** size of heap limits can be determined by invoking
+** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
+**
+** ^Setting the heap limits to zero disables the heap limiter mechanism.
+**
+** ^The soft heap limit may not be greater than the hard heap limit.
+** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
+** is invoked with a value of N that is greater than the hard heap limit,
+** the the soft heap limit is set to the value of the hard heap limit.
+** ^The soft heap limit is automatically enabled whenever the hard heap
+** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
+** the soft heap limit is outside the range of 1..N, then the soft heap
+** limit is set to N.  ^Invoking sqlite3_soft_heap_limit64(0) when the
+** hard heap limit is enabled makes the soft heap limit equal to the
+** hard heap limit.
+**
+** The memory allocation limits can also be adjusted using
+** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
+**
+** ^(The heap limits are not enforced in the current implementation
 ** if one or more of following conditions are true:
 **
 ** <ul>
-** <li> The soft heap limit is set to zero.
+** <li> The limit value is set to zero.
 ** <li> Memory accounting is disabled using a combination of the
 **      [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
 **      the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
@@ -6150,21 +6175,11 @@ int sqlite3_db_release_memory(sqlite3*);
 **      from the heap.
 ** </ul>)^
 **
-** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), 
-** the soft heap limit is enforced
-** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
-** compile-time option is invoked.  With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
-** the soft heap limit is enforced on every memory allocation.  Without
-** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
-** when memory is allocated by the page cache.  Testing suggests that because
-** the page cache is the predominate memory user in SQLite, most
-** applications will achieve adequate soft heap limit enforcement without
-** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
-**
-** The circumstances under which SQLite will enforce the soft heap limit may
+** The circumstances under which SQLite will enforce the heap limits may
 ** changes in future releases of SQLite.
 */
 sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
 
 /*
 ** CAPI3REF: Deprecated Soft Heap Limit Interface
index 416ac94231a3a65f3aef1e4e7ee635327aa73945..f7a0386a7a8207e43b3ed2520e4dfbb622f47a96 100644 (file)
@@ -324,6 +324,7 @@ struct sqlite3_api_routines {
   int (*value_frombind)(sqlite3_value*);
   /* Version 3.30.0 and later */
   int (*drop_modules)(sqlite3*,const char**);
+  sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
 };
 
 /*
@@ -618,6 +619,7 @@ typedef int (*sqlite3_loadext_entry)(
 #define sqlite3_value_frombind         sqlite3_api->frombind
 /* Version 3.30.0 and later */
 #define sqlite3_drop_modules           sqlite3_api->drop_modules
+#define sqlite3_hard_heap_limit64      sqlite3_api->hard_heap_limit64
 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
 
 #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
index ffd6091fa36623acd4b1fecc14ae68510d2355c4..a428be62b90c7c4a6d69ccc4ebb874330c466b28 100644 (file)
@@ -5526,6 +5526,33 @@ static int SQLITE_TCLAPI test_soft_heap_limit(
   return TCL_OK;
 }
 
+/*
+** Usage:  sqlite3_hard_heap_limit ?N?
+**
+** Query or set the hard heap limit for the current thread.  The
+** limit is only changed if the N is present.  The previous limit
+** is returned.
+*/
+static int SQLITE_TCLAPI test_hard_heap_limit(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  sqlite3_int64 amt;
+  Tcl_WideInt N = -1;
+  if( objc!=1 && objc!=2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "?N?");
+    return TCL_ERROR;
+  }
+  if( objc==2 ){
+    if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
+  }
+  amt = sqlite3_hard_heap_limit64(N);
+  Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
+  return TCL_OK;
+}
+
 /*
 ** Usage:   sqlite3_thread_cleanup
 **
@@ -7973,6 +8000,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_db_filename",           test_db_filename,        0},
      { "sqlite3_db_readonly",           test_db_readonly,        0},
      { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0},
+     { "sqlite3_soft_heap_limit64",     test_soft_heap_limit,    0},
+     { "sqlite3_hard_heap_limit64",     test_hard_heap_limit,    0},
      { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},
      { "sqlite3_pager_refcounts",       test_pager_refcounts,    0},
 
index 4979f59b58eac14c78de59e119d5ed23ed837f6b..e6e7a1df26ed0021ea78f07d2e8cb208a6dc878f 100644 (file)
@@ -66,7 +66,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
     va_start(ap, zFormat);
     sqlite3_str_vappendf(&acc, zFormat, ap);
     va_end(ap);
-    assert( acc.nChar>0 );
+    assert( acc.nChar>0 || acc.accError );
     sqlite3_str_append(&acc, "\n", 1);
   }
   sqlite3StrAccumFinish(&acc);
index 4d52aedea9d0b0d5a2df4197f161369a04458fc0..f1d2415de22f65714c88927e310f8eb74e6f8edc 100644 (file)
@@ -453,6 +453,9 @@ static unsigned int mxProgressCb = 2000;
 /* Maximum string length in SQLite */
 static int lengthLimit = 1000000;
 
+/* Limit on the amount of heap memory that can be used */
+static sqlite3_int64 heapLimit = 1000000000;
+
 /* Maximum byte-code program length in SQLite */
 static int vdbeOpLimit = 25000;
 
@@ -777,6 +780,7 @@ int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte){
   if( lengthLimit>0 ){
     sqlite3_limit(cx.db, SQLITE_LIMIT_LENGTH, lengthLimit);
   }
+  sqlite3_hard_heap_limit64(heapLimit);
 
   if( nDb>=20 && aDb[18]==2 && aDb[19]==2 ){
     aDb[18] = aDb[19] = 1;
@@ -1341,7 +1345,7 @@ int main(int argc, char **argv){
   int cellSzCkFlag = 0;        /* --cell-size-check */
   int sqlFuzz = 0;             /* True for SQL fuzz. False for DB fuzz */
   int iTimeout = 120;          /* Default 120-second timeout */
-  int nMem = 0;                /* Memory limit */
+  int nMem = 0;                /* Memory limit override */
   int nMemThisDb = 0;          /* Memory limit set by the CONFIG table */
   char *zExpDb = 0;            /* Write Databases to files in this directory */
   char *zExpSql = 0;           /* Write SQL to files in this directory */
@@ -1391,13 +1395,8 @@ int main(int argc, char **argv){
         infoFlag = 1;
       }else
       if( strcmp(z,"limit-mem")==0 ){
-#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
-        fatalError("the %s option requires -DSQLITE_ENABLE_MEMSYS5 or _MEMSYS3",
-                   argv[i]);
-#else
         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
         nMem = integerValue(argv[++i]);
-#endif
       }else
       if( strcmp(z,"limit-vdbe")==0 ){
         vdbeLimitFlag = 1;
@@ -1586,14 +1585,9 @@ int main(int argc, char **argv){
           ossFuzzThisDb = sqlite3_column_int(pStmt,1);
           if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb);
         }
-        if( strcmp(zName, "limit-mem")==0 && !nativeMalloc ){
-#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
-          fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5"
-                     " or _MEMSYS3");
-#else
+        if( strcmp(zName, "limit-mem")==0 ){
           nMemThisDb = sqlite3_column_int(pStmt,1);
           if( verboseFlag ) printf("Config: limit-mem=%d\n", nMemThisDb);
-#endif
         }
       }
       sqlite3_finalize(pStmt);
@@ -1720,12 +1714,18 @@ int main(int argc, char **argv){
 
     /* Limit available memory, if requested */
     sqlite3_shutdown();
-    if( nMemThisDb>0 && !nativeMalloc ){
-      pHeap = realloc(pHeap, nMemThisDb);
-      if( pHeap==0 ){
-        fatalError("failed to allocate %d bytes of heap memory", nMem);
+    if( nMemThisDb>0 && nMem==0 ){
+      if( !nativeMalloc ){
+        pHeap = realloc(pHeap, nMemThisDb);
+        if( pHeap==0 ){
+          fatalError("failed to allocate %d bytes of heap memory", nMem);
+        }
+        sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
+      }else{
+        sqlite3_hard_heap_limit64((sqlite3_int64)nMemThisDb);
       }
-      sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
+    }else{
+      sqlite3_hard_heap_limit64(0);
     }
 
     /* Disable lookaside with the --native-malloc option */
index 3b1017f7267f653188186d89e1b21069b0857c08..b0156a640e6e23145238039d348b92561062966c 100644 (file)
@@ -155,6 +155,9 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   /* Set a limit on the maximum size of a prepared statement */
   sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, 25000);
 
+  /* Limit total memory available to SQLite to 20MB */
+  sqlite3_hard_heap_limit64(20000000);
+
   /* Set a limit on the maximum length of a string or BLOB.  Without this
   ** limit, fuzzers will invoke randomblob(N) for a large N, and the process
   ** will timeout trying to generate the huge blob */
index 6efb59bd6d9afa15bf214e9b823f5ff9f909f385..05c52343f095a629169493a65e898bb46e86f3c2 100644 (file)
@@ -388,6 +388,7 @@ proc print_help_and_quit {} {
   puts {Options:
   --pause                  Wait for user input before continuing
   --soft-heap-limit=N      Set the soft-heap-limit to N
+  --hard-heap-limit=N      Set the hard-heap-limit to N
   --maxerror=N             Quit after N errors
   --verbose=(0|1)          Control the amount of output.  Default '1'
   --output=FILE            set --verbose=2 and output to FILE.  Implies -q
@@ -408,6 +409,7 @@ if {[info exists cmdlinearg]==0} {
   #
   #   --pause
   #   --soft-heap-limit=NN
+  #   --hard-heap-limit=NN
   #   --maxerror=NN
   #   --malloctrace=N
   #   --backtrace=N
@@ -424,6 +426,7 @@ if {[info exists cmdlinearg]==0} {
   #   --help
   #
   set cmdlinearg(soft-heap-limit)    0
+  set cmdlinearg(hard-heap-limit)    0
   set cmdlinearg(maxerror)        1000
   set cmdlinearg(malloctrace)        0
   set cmdlinearg(backtrace)         10
@@ -450,6 +453,9 @@ if {[info exists cmdlinearg]==0} {
       {^-+soft-heap-limit=.+$} {
         foreach {dummy cmdlinearg(soft-heap-limit)} [split $a =] break
       }
+      {^-+hard-heap-limit=.+$} {
+        foreach {dummy cmdlinearg(hard-heap-limit)} [split $a =] break
+      }
       {^-+maxerror=.+$} {
         foreach {dummy cmdlinearg(maxerror)} [split $a =] break
       }
@@ -586,7 +592,8 @@ if {[info exists cmdlinearg]==0} {
 # way if an individual test file changes the soft-heap-limit, it
 # will be reset at the start of the next test file.
 #
-sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
+sqlite3_soft_heap_limit64 $cmdlinearg(soft-heap-limit)
+sqlite3_hard_heap_limit64 $cmdlinearg(hard-heap-limit)
 
 # Create a test database
 #
@@ -1207,7 +1214,8 @@ proc finalize_testing {} {
   db close
   sqlite3_reset_auto_extension
 
-  sqlite3_soft_heap_limit 0
+  sqlite3_soft_heap_limit64 0
+  sqlite3_hard_heap_limit64 0
   set nTest [incr_ntest]
   set nErr [set_test_counter errors]
 
index 832153916e70c505814aafecfbe4afc94c86e435..f19ecab694732b9fe4d908625531182b5b9ceefe 100644 (file)
@@ -406,6 +406,9 @@ set pragma_def {
   NAME: soft_heap_limit
   FLAG: Result0
 
+  NAME: hard_heap_limit
+  FLAG: Result0
+
   NAME: threads
   FLAG: Result0