From: drh <> Date: Sat, 27 Sep 2025 15:03:11 +0000 (+0000) Subject: Rework the bounds calculations on generate_series() in an attempt to X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=54f296389c4b213d4c2af3cb34e3181354956b9d;p=thirdparty%2Fsqlite.git Rework the bounds calculations on generate_series() in an attempt to avoid signed integer overflow when the bounds are ridiculous values. FossilOrigin-Name: 3d9148c7d7379a34a0c2a33a1eb2562234868bc0b14c3d16990b33e52fd4ebc5 --- diff --git a/ext/misc/series.c b/ext/misc/series.c index cb65c3e51b..0ea5329b26 100644 --- a/ext/misc/series.c +++ b/ext/misc/series.c @@ -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( iTermss.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; + } } diff --git a/manifest b/manifest index 083b1bedf9..60d2abb520 100644 --- 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. diff --git a/manifest.uuid b/manifest.uuid index bf59fd1bbb..0367d45468 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b44650f907e9cb4ec908bb7525488e309946fac9d84cdac4cdde730527a440a9 +3d9148c7d7379a34a0c2a33a1eb2562234868bc0b14c3d16990b33e52fd4ebc5 diff --git a/test/tabfunc01.test b/test/tabfunc01.test index 0e29c35683..0fe030634c 100644 --- a/test/tabfunc01.test +++ b/test/tabfunc01.test @@ -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 #