SQLite User Forum

Query triggers Segmentation Fault
Login

Query triggers Segmentation Fault

(1) By Yu Liang (LY1598773890) on 2021-05-19 19:13:23 [link] [source]

Hi all.

For query:

CREATE TABLE v0 ( v2 INTEGER );
CREATE TABLE v3 ( v5 INTEGER );
WITH v0 AS ( SELECT * FROM v3 ) UPDATE v0 SET v2 = 'x' FROM v3;

Segmentation Fault triggered. Address Sanitizer outputs the following information:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==3922846==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x0000007d7f8c bp 0x7fff139364d0 sp 0x7fff13936380 T0)
==3922846==The signal is caused by a READ memory access.
==3922846==Hint: address points to the zero page.
    #0 0x7d7f8c in sqlite3ExprVectorSize /home/hong/sqlite-asan-build/sqlite3.c:101589:18
    #1 0x7d7f8c in sqlite3ExprIsVector /home/hong/sqlite-asan-build/sqlite3.c:101579:10
    #2 0x7d7f8c in substExpr /home/hong/sqlite-asan-build/sqlite3.c:135568:11
    #3 0x7d7310 in substExprList /home/hong/sqlite-asan-build/sqlite3.c:135635:25
    #4 0x7d7310 in substSelect /home/hong/sqlite-asan-build/sqlite3.c:135648:5
    #5 0x6d726d in flattenSubquery /home/hong/sqlite-asan-build/sqlite3.c:136313:7
    #6 0x6d726d in sqlite3Select /home/hong/sqlite-asan-build/sqlite3.c:138246:9
    #7 0x862613 in updateFromSelect /home/hong/sqlite-asan-build/sqlite3.c:141142:3
    #8 0x7136e0 in sqlite3Update /home/hong/sqlite-asan-build/sqlite3.c:141555:9
    #9 0x6902b8 in yy_reduce /home/hong/sqlite-asan-build/sqlite3.c:161919:3
    #10 0x56e010 in sqlite3Parser /home/hong/sqlite-asan-build/sqlite3.c:162963:15
    #11 0x56e010 in sqlite3RunParser /home/hong/sqlite-asan-build/sqlite3.c:164259:5
    #12 0x663e3d in sqlite3Prepare /home/hong/sqlite-asan-build/sqlite3.c:131652:5
    #13 0x56a6af in sqlite3LockAndPrepare /home/hong/sqlite-asan-build/sqlite3.c:131727:10
    #14 0x53e804 in sqlite3_prepare_v2 /home/hong/sqlite-asan-build/sqlite3.c:131812:8
    #15 0x4f5482 in shell_exec /home/hong/sqlite-asan-build/shell.c:13602:10
    #16 0x52a90f in runOneSqlLine /home/hong/sqlite-asan-build/shell.c:20626:8
    #17 0x4f9e8b in process_input /home/hong/sqlite-asan-build/shell.c:20726:17
    #18 0x4d6e10 in main /home/hong/sqlite-asan-build/shell.c
    #19 0x7fc161e9e0b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
    #20 0x41c63d in _start (/home/hong/sqlite-asan-build/sqlite3+0x41c63d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/hong/sqlite-asan-build/sqlite3.c:101589:18 in sqlite3ExprVectorSize
==3922846==ABORTING

This behavior can be reproduced by one of the latest development version, fossil: b480aacb3430a789d98ffd81a1886bbbc3cda5b0e736ec9a3e2b463db2a3b3ad, but seems not affecting the stable release: tested with SQLite version 3.32.3 with correct run through.

Look forward to your reply.

(2) By Richard Hipp (drh) on 2021-05-19 21:59:57 in reply to 1 [source]

The segfault is due to recent, unreleased changes. Specifically, the removal of "rowid" from VIEWs. So, you shouldn't be able to segfault an official release version of SQLite using the example above.

However, this example does point to a name resolution problem with common table expressions. In particular, the following SQL results in an incorrect answer:

CREATE TABLE t1(k);
CREATE TABLE log(k, cte_map, main_map);
CREATE TABLE map(k, v);
INSERT INTO map VALUES(1, 'main1'), (2, 'main2');
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
  INSERT INTO log
      WITH map(k,v) AS (VALUES(1,'cte1'),(2,'cte2'))
      SELECT
        new.k,
        (SELECT v FROM map WHERE k=new.k),
        (SELECT v FROM main.map WHERE k=new.k);
END;
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
SELECT * FROM log;

The output here should be:

┌───┬─────────┬──────────┐
│ k │ cte_map │ main_map │
├───┼─────────┼──────────┤
│ 1 │ cte1    │ main1    │
│ 2 │ cte2    │ main2    │
└───┴─────────┴──────────┘

But instead we get:

┌───┬─────────┬──────────┐
│ k │ cte_map │ main_map │
├───┼─────────┼──────────┤
│ 1 │ cte1    │ cte1     │
│ 2 │ cte2    │ cte2     │
└───┴─────────┴──────────┘

The problem is that "main.map" in the trigger is getting bound to the common-table expression called "map" rather than to the table called "map". This name resolution problem has existed ever since common-table expression support was added to SQLite with version 3.8.3 (2014-02-03).

Check-in 0f0959c6f95046e8 should resolve the segfault, or at least the specific example you provide above. But consider that check-in to be an interim fix. The deeper problem of name resolution inside of common table expressions will take a bit more work, and might not be fixed for another day or two.

(3) By Yu Liang (LY1598773890) on 2021-05-20 00:35:02 in reply to 2 [link] [source]

Thank you for patch and the explanation.

(4) By Richard Hipp (drh) on 2021-05-20 00:53:25 in reply to 2 [link] [source]

Check-in 5614279daff5007d is an alternative fix that handles both the CTE name resolution problem and the original segfault.

(5) By Mark Lawrence (mark) on 2021-05-21 07:55:08 in reply to 2 [link] [source]

Richard, Your use of a CTE in the trigger above appears to contradict chapter 5 of https://sqlite.org/lang_with.html. Has something changed or do I misunderstand the documentation?