sqlite3_step after sqlite3_finalize: what is the expected behavior?
(1.1) By Alain (McMartin) on 2021-09-18 13:24:01 edited from 1.0 [link]
Up until [check-in f7ab01f2](https://sqlite.org/src/timeline?c=f7ab01f254cd9d70), the following program would work: ``` #include <sqlite3.h> #include <assert.h> #include <string.h> #include <stdio.h> int main() { sqlite3 *db; sqlite3_stmt *stmt; int rc; rc = sqlite3_open(":memory:", &db); assert(rc == SQLITE_OK); const char* sql = "SELECT 0 WHERE 0;"; rc = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, 0); assert(rc == SQLITE_OK); rc = sqlite3_finalize(stmt); assert(rc == SQLITE_OK); rc = sqlite3_step(stmt); assert(rc == SQLITE_MISUSE); rc = sqlite3_close(db); assert(rc == SQLITE_OK); printf("All good!\n"); return 0; } ``` Calling `sqlite3_step` on a finalized statement returned `SQLITE_MISUSE`, which seems sensible and matches the (current) documentation of `sqlite3_step`: ``` ** [SQLITE_MISUSE] means that the this routine was called inappropriately. ** Perhaps it was called on a [prepared statement] that has ** already been [sqlite3_finalize | finalized] ``` Then, in [check-in 52a12e47](https://sqlite.org/src/timeline?c=52a12e47de887441), the default lookaside configuration was changed and that program crashes with a segmentation fault, which matches the (current) documentation of `sqlite3_finalize`: ``` ** It is a grievous error for the application to try to use ** a prepared statement after it has been finalized. Any use of a prepared ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. ``` So what is the expected behavior? If the documentation of `sqlite3_finalize` holds the truth, then the documentation of `sqlite3_step` deserves an update to avoid confusion. Also, is there any case where using a prepared statement that has been finalized doesn't crash?
(2.1) By Larry Brasfield (larrybr) on 2021-09-18 13:39:31 edited from 2.0 in reply to 1.0 [link]
> If the documentation of sqlite3_finalize holds the truth ... It does. The phrase "can result in undefined behavior" includes the possibility of behavior not recognized as grievous. A better phrasing might be "results in undefined behavior" (which includes not seg-faulting), but that invites the same perplexity you have shared. > then the documentation of sqlite3_step deserves an update to avoid confusion. I am not seeing it that way yet. What specific part of the doc you quoted for the SQLITE_MISUSE return do you believe to be false or confusing? If that return is seen, it means what is claimed. That logical (if-then) relation does not imply its converse, (which would be "If this routine is called inappropriately, then SQLITE_MISUSE will be returned.") Among the possible outcomes of an inappropriate call is a seg-fault, as is documented explicitly and is implicitly included in "undefined behavior". At present, I am disinclined to further elaborate that documentation merely to make explicit such a result of <u>[elementary logic](https://en.wikipedia.org/wiki/Converse_(logic\) )</u>. Doing so would be in the same category as adding, to every positive assertion, something like: "This does not mean P, Q, R ... (without logical end)."
(3) By Alain (McMartin) on 2021-09-18 14:40:28 in reply to 2.1
Thanks a lot for the very quick answer! After re-reading these pieces of documentation, I agree that they don't contradict each other, nor the previous or current behavior. I guess I need to come up with a way of keeping track of which prepared statements have been finalized, in my own code.