SQLite

Ticket Change Details
Login
Overview

Artifact ID: 580eefd3a106fa0817ae2c2b25797a9841fc8b8938e6df86f44b4b878334c885
Ticket: be436a7f4587ce517ddc36f3670073563ecc6622
Use-after-free on schema change where RTREE is used inside of a trigger
User & Date: drh 2017-08-17 02:25:13
Changes

  1. icomment:
    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.
    
  2. login: "drh"
  3. mimetype: "text/x-fossil-wiki"
  4. severity changed to: "Severe"
  5. status changed to: "Open"
  6. title changed to:
    Use-after-free on schema change where RTREE is used inside of a trigger
    
  7. type changed to: "Code_Defect"