(text/x-fossil-wiki)
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:
<blockquote><verbatim>
#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;
}
</verbatim></blockquote>
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.
|