]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Rework the bounds calculations on generate_series() in an attempt to
authordrh <>
Sat, 27 Sep 2025 15:03:11 +0000 (15:03 +0000)
committerdrh <>
Sat, 27 Sep 2025 15:03:11 +0000 (15:03 +0000)
avoid signed integer overflow when the bounds are ridiculous values.

FossilOrigin-Name: 3d9148c7d7379a34a0c2a33a1eb2562234868bc0b14c3d16990b33e52fd4ebc5

ext/misc/series.c
manifest
manifest.uuid
test/tabfunc01.test

index cb65c3e51b19ce0c74f05a92b5e3aa3fe6b76889..0ea5329b269e7f2f40f735bc1eca213260655569 100644 (file)
@@ -163,6 +163,28 @@ typedef struct SequenceSpec {
   u8 isReversing;              /* Sequence is being reverse generated */
 } SequenceSpec;
 
+/*
+** Return the number of steps between pSS->iBase and pSS->iTerm if
+** the step width is pSS->iStep.
+*/
+static sqlite3_uint64 seriesSteps(SequenceSpec *pSS){
+  sqlite3_uint64 uBase, uTerm, uStep, uSpan;
+  assert( pSS->iStep!=0 );
+  assert( sizeof(uBase)==sizeof(&pSS->iBase) );
+  assert( sizeof(uTerm)==sizeof(&pSS->iTerm) );
+  assert( sizeof(uStep)==sizeof(&pSS->iStep) );
+  memcpy(&uBase, &pSS->iBase, sizeof(uBase));
+  memcpy(&uTerm, &pSS->iTerm, sizeof(uTerm));
+  memcpy(&uStep, &pSS->iStep, sizeof(uStep));
+  if( pSS->iStep>0 ){
+    uSpan = uTerm - uBase;
+  }else{
+    uSpan = uBase - uTerm;
+    uStep = 1 + ~uStep;
+  }
+  return uSpan/uStep;
+}
+
 /*
 ** Prepare a SequenceSpec for use in generating an integer series
 ** given initialized iBase, iTerm and iStep values. Sequence is
@@ -547,7 +569,7 @@ static int seriesFilter(
       if( pCur->ss.iTerm>iMax ){
         pCur->ss.iTerm = iMax;
       }
-    }else{
+    }else if( pCur->ss.iStep>SMALLEST_INT64 ){
       sqlite3_int64 szStep = -pCur->ss.iStep;
       assert( szStep>0 );
       if( pCur->ss.iBase>iMax ){
@@ -561,23 +583,22 @@ static int seriesFilter(
   }
 
   /* Apply LIMIT and OFFSET constraints, if any */
+  assert( pCur->ss.iStep!=0 );
   if( idxNum & 0x20 ){
+    sqlite3_uint64 nStep;
     if( iOffset>0 ){
-      pCur->ss.iBase += pCur->ss.iStep*iOffset;
-    }
-    if( iLimit>=0 ){
-      sqlite3_int64 iTerm;
-      sqlite3_int64 mxLimit;
-      assert( pCur->ss.iStep>0 );
-      mxLimit = (LARGEST_INT64 - pCur->ss.iBase)/pCur->ss.iStep;
-      if( iLimit>mxLimit ) iLimit = mxLimit;
-      iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
-      if( pCur->ss.iStep<0 ){
-        if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
+      if( seriesSteps(&pCur->ss) < (sqlite3_uint64)iOffset ){
+        returnNoRows = 1;
+        iLimit = -1;
       }else{
-        if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
+        pCur->ss.iBase += pCur->ss.iStep*iOffset;
       }
     }
+    if( iLimit>=0
+     && (nStep = seriesSteps(&pCur->ss)) > (sqlite3_uint64)iLimit
+    ){
+      pCur->ss.iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
+    }
   }
 
 
index 083b1bedf92a5005e58bc3b5c48e52ac79d208cd..60d2abb520eab0489fb82efc7416527dc5871f9b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C ext/wasm/c-pp.c:\sadd\s#savepoint\ssupport.\sConsolidate\show\sthe\sdiverse\ssqlite3_stmt\shandles\sare\smanaged.
-D 2025-09-27T13:34:02.718
+C Rework\sthe\sbounds\scalculations\son\sgenerate_series()\sin\san\sattempt\sto\navoid\ssigned\sinteger\soverflow\swhen\sthe\sbounds\sare\sridiculous\svalues.
+D 2025-09-27T15:03:11.176
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -393,7 +393,7 @@ F ext/misc/regexp.c 548151f3e57506fda678e6a65e85a763f4eece653287e1ad44e167f9485e
 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
 F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
 F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
-F ext/misc/series.c 49b9b0e2bd60176796d55b0f2dc03f4b777b4e2bbee49d508d0685fa4df60f41
+F ext/misc/series.c 31437e7253fbcc4cc62e9d419b6528e1a83802e6abfd5b12c90d90e044d5dda3
 F ext/misc/sha1.c cb5002148c2661b5946f34561701e9105e9d339b713ec8ac057fd888b196dcb9
 F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
@@ -1678,7 +1678,7 @@ F test/sync.test a619e407ede58a7b6e3e44375328628559fc9695a9c24c47cb5690a866b0031
 F test/sync2.test 06152269ed73128782c450c355988fe8dd794d305833af75e1a5e79edd4dae47
 F test/syscall.test a067468b43b8cb2305e9f9fe414e5f40c875bb5d2cba5f00b8154396e95fcf37
 F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test 8a484fe8b19fc24844f72ca1ceb7c9ae8c9a6bca000a5c6ccab5d89f5cfbea4a
+F test/tabfunc01.test f9a612a6a021e9f0d8df7d182762fea55dff671c29a5a15100cad4388e08151c
 F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
 F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -2169,8 +2169,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P b05c47009120840f74955114082f3a9c1206a81bd935a503fc359b5bde61c996
-R 5c9bc3e1c5ff8428ad8c5e411548be45
-U stephan
-Z 0c4774a9e741ee60e5e425d698f46673
+P b44650f907e9cb4ec908bb7525488e309946fac9d84cdac4cdde730527a440a9
+R d5846da0ab3c8c6a5964b44c05b2978e
+U drh
+Z fa03ae8701fe595d404c20bdd78a00d1
 # Remove this line to create a well-formed Fossil manifest.
index bf59fd1bbb5555e7d42af0e97926f1b61b439e55..0367d45468a06799c879628098edb19afd87ee6e 100644 (file)
@@ -1 +1 @@
-b44650f907e9cb4ec908bb7525488e309946fac9d84cdac4cdde730527a440a9
+3d9148c7d7379a34a0c2a33a1eb2562234868bc0b14c3d16990b33e52fd4ebc5
index 0e29c356832b9f879a5fe0164b3094550e644a99..0fe030634c396b24a5a16654958a91142b980ede 100644 (file)
@@ -418,6 +418,66 @@ do_execsql_test tabfunc01-920 {
   ) LIMIT -1 OFFSET 0;
 } {1 2 3 4 5 6 7 8 9 10 101 102 103 104}
 
+# Also:  https://sqlite.org/forum/forumpost/ce1a06c2c8
+#
+do_execsql_test tabfunc01-930 {
+  SELECT * FROM generate_series(9223372036854775807,
+                                -9223372036854775808,
+                                -9223372036854775808);
+} {9223372036854775807 -1}
+do_execsql_test tabfunc01-931 {
+  SELECT * FROM generate_series(9223372036854775807,
+                                -9223372036854775808,
+                                -9223372036854775808)
+   LIMIT 100 OFFSET 1;
+} {-1}
+do_execsql_test tabfunc01-932 {
+  SELECT * FROM generate_series(9223372036854775807,
+                                -9223372036854775808,
+                                -9223372036854775808)
+   LIMIT 100 OFFSET 2;
+} {}
+do_execsql_test tabfunc01-933 {
+  SELECT * FROM generate_series(9223372036854775807,
+                                -9223372036854775808,
+                                -9223372036854775808)
+   LIMIT 100 OFFSET 9223372036854775807;
+} {}
+do_execsql_test tabfunc01-940 {
+  SELECT * FROM generate_series(1,11,2);
+} {1 3 5 7 9 11}
+do_execsql_test tabfunc01-941 {
+  SELECT * FROM generate_series(1,11,2) LIMIT 100 OFFSET 4;
+} {9 11}
+do_execsql_test tabfunc01-942 {
+  SELECT * FROM generate_series(1,11,2) LIMIT 100 OFFSET 5;
+} {11}
+do_execsql_test tabfunc01-943 {
+  SELECT * FROM generate_series(1,11,2) LIMIT 100 OFFSET 6;
+} {}
+do_execsql_test tabfunc01-944 {
+  SELECT * FROM generate_series(1,11,2) LIMIT 100 OFFSET 7;
+} {}
+do_execsql_test tabfunc01-945 {
+  SELECT * FROM generate_series(1,11,2) LIMIT 100 OFFSET 9223372036854775807;
+} {}
+do_execsql_test tabfunc01-950 {
+  SELECT * FROM generate_series(1,11,1) LIMIT 100 OFFSET 10;
+} {11}
+do_execsql_test tabfunc01-951 {
+  SELECT * FROM generate_series(1,11,2) LIMIT 100 OFFSET 9223372036854775807;
+} {}
+do_execsql_test tabfunc01-952 {
+  SELECT * FROM generate_series(11,1,-1) LIMIT 100 OFFSET 10;
+} {1}
+do_execsql_test tabfunc01-953 {
+  SELECT * FROM generate_series(11,1,-1) LIMIT 100 OFFSET 9223372036854775807;
+} {}
+do_execsql_test tabfunc01-954 {
+  SELECT * FROM generate_series(1,11,1) LIMIT 3 OFFSET 3;
+} {4 5 6}
+
+
 #-------------------------------------------------------------------------
 # Forum post https://sqlite.org/forum/forumpost/e7c3ae1215
 #