Ticket Hash: | be436a7f4587ce517ddc36f3670073563ecc6622 | |||
Title: | Use-after-free on schema change where RTREE is used inside of a trigger | |||
Status: | Fixed | Type: | Code_Defect | |
Severity: | Severe | Priority: | Immediate | |
Subsystem: | Unknown | Resolution: | Fixed | |
Last Modified: | 2017-08-17 14:48:10 | |||
Version Found In: | ||||
User Comments: | ||||
drh added on 2017-08-17 02:25:13:
If a virtual table invokes sqlite3_step() as part of its xConnect method (as RTREE does) and if that virtual table is used inside of a trigger and if an external schema change occurs on the first use of that trigger, then the xConnect method will provoke a schema reset that will delete a pointer to the trigger out from under the query planner, resulting in a use-after-free and a probable segfault. The following C code demonstrates the problems: #include <stdio.h> #include <unistd.h> #include "sqlite3.h" int main(int argc, char *argv){ sqlite3 *db1, *db2; unlink("test.db"); printf("VERSION: %s\n", sqlite3_libversion()); sqlite3_open("test.db", &db1); sqlite3_exec(db1, "CREATE VIRTUAL TABLE r1 USING rtree(id, x1, x2, y1, y2);\n" "CREATE TABLE t1(id, x1, x2, y1, y2);\n" "CREATE TABLE log(l);\n" "CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN\n" " INSERT INTO r1 VALUES(new.id, new.x1, new.x2, new.y1, new.y2);\n" " INSERT INTO log VALUES('r1: ' || new.id);\n" "END;", 0, 0, 0); sqlite3_close(db1); sqlite3_open("test.db", &db1); sqlite3_open("test.db", &db2); sqlite3_exec(db1, "INSERT INTO log VALUES('startup');", 0, 0, 0); sqlite3_exec(db2, "CREATE TABLE newtab(a,b);", 0, 0, 0); sqlite3_exec(db1, "INSERT INTO t1 VALUES(1,2,3,4,5);", 0, 0, 0); sqlite3_close(db1); sqlite3_close(db2); return 0; } This problem appears to have existed in the virtual table implementation forever. The test program above first began to fail with check-in [ebc9433f] on 2010-02-16 (SQLite version 3.6.23) because that check-in was the first to cause RTREE to invoke sqlite3_step() from within its xConnect method. |