Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a problem in the sessions module causing sqlite3session_apply_strm() to allocate enough memory for the entire input buffer - which defeats the point of a streaming interface. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
7594e60935b0b5dcf764476dccdf9b40 |
User & Date: | dan 2018-04-06 16:22:25.544 |
Context
2018-04-06
| ||
19:12 | Enhance LEMON to show precendence of symbols and all rules in the report that is generated in parallel to the parser. (check-in: 602fbd8149 user: drh tags: trunk) | |
16:22 | Fix a problem in the sessions module causing sqlite3session_apply_strm() to allocate enough memory for the entire input buffer - which defeats the point of a streaming interface. (check-in: 7594e60935 user: dan tags: trunk) | |
2018-04-05
| ||
16:26 | Fix an instance where an uninitialized VM register might be accessed. Fix for [093420fc0]. This problem was found by OSSFuzz. (check-in: a3b02db746 user: dan tags: trunk) | |
Changes
Changes to ext/session/sessionG.test.
︙ | ︙ | |||
200 201 202 203 204 205 206 207 208 209 210 211 | db2 eval { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 7 8 9} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | db2 eval { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 7 8 9} #------------------------------------------------------------------------- reset_db db func number_name number_name do_execsql_test 6.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); CREATE UNIQUE INDEX t1b ON t1(b); WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 ) INSERT INTO t1 SELECT i, number_name(i) FROM s; } do_test 6.1 { db eval BEGIN set ::C [changeset_from_sql { DELETE FROM t1; WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 ) INSERT INTO t1 SELECT i, number_name(i+1) FROM s; }] db eval ROLLBACK execsql { SELECT count(*) FROM t1 WHERE number_name(a) IS NOT b } } {0} proc xConflict {args} { exit ; return "OMIT" } do_test 6.2 { sqlite3changeset_apply db $C xConflict } {} do_execsql_test 6.3 { SELECT count(*) FROM t1; } {1000} do_execsql_test 6.4 { SELECT count(*) FROM t1 WHERE number_name(a+1) IS NOT b; } {0} # db eval { SELECT * FROM t1 } { puts "$a || $b" } finish_test |
Changes to ext/session/session_common.tcl.
︙ | ︙ | |||
166 167 168 169 170 171 172 | proc changeset_to_list {c} { set list [list] sqlite3session_foreach elem $c { lappend list $elem } lsort $list } | > > > > > > > > > > > > > > > > > > > > > > > > > > | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | proc changeset_to_list {c} { set list [list] sqlite3session_foreach elem $c { lappend list $elem } lsort $list } set ones {zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen} set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} proc number_name {n} { if {$n>=1000} { set txt "[number_name [expr {$n/1000}]] thousand" set n [expr {$n%1000}] } else { set txt {} } if {$n>=100} { append txt " [lindex $::ones [expr {$n/100}]] hundred" set n [expr {$n%100}] } if {$n>=20} { append txt " [lindex $::tens [expr {$n/10}]]" set n [expr {$n%10}] } if {$n>0} { append txt " [lindex $::ones $n]" } set txt [string trim $txt] if {$txt==""} {set txt zero} return $txt } |
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
64 65 66 67 68 69 70 | /* ** An object of this type is used internally as an abstraction for ** input data. Input data may be supplied either as a single large buffer ** (e.g. sqlite3changeset_start()) or using a stream function (e.g. ** sqlite3changeset_start_strm()). */ struct SessionInput { | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | /* ** An object of this type is used internally as an abstraction for ** input data. Input data may be supplied either as a single large buffer ** (e.g. sqlite3changeset_start()) or using a stream function (e.g. ** sqlite3changeset_start_strm()). */ struct SessionInput { int bNoDiscard; /* If true, do not discard in InputBuffer() */ int iCurrent; /* Offset in aData[] of current change */ int iNext; /* Offset in aData[] of next change */ u8 *aData; /* Pointer to buffer containing changeset */ int nData; /* Number of bytes in aData */ SessionBuffer buf; /* Current read buffer */ int (*xInput)(void*, void*, int*); /* Input stream call (or NULL) */ |
︙ | ︙ | |||
2589 2590 2591 2592 2593 2594 2595 | } /* ** If the SessionInput object passed as the only argument is a streaming ** object and the buffer is full, discard some data to free up space. */ static void sessionDiscardData(SessionInput *pIn){ | | | 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 | } /* ** If the SessionInput object passed as the only argument is a streaming ** object and the buffer is full, discard some data to free up space. */ static void sessionDiscardData(SessionInput *pIn){ if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ int nMove = pIn->buf.nBuf - pIn->iNext; assert( nMove>=0 ); if( nMove>0 ){ memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); } pIn->buf.nBuf -= pIn->iNext; pIn->iNext = 0; |
︙ | ︙ |