C
48
sqlite3 db
Guest on 10th May 2022 05:49:09 PM
#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
/* Instructions: grab a read lock, then try two inserts without resetting.
* $ rm a.db
* $ sqlite3 a.db < write-misuse-demo.sql
* $ sqlite3 a.db
* sqlite> BEGIN; SELECT * FROM c;
* a|b
* c|d
* sqlite> [stay at prompt]
*
* Now, in another shell:
* ./write-misuse-demo.sql a.db
* Insert 1 SQL error 5: database is locked
* Insert 2 succeeded, 1 rows changed [?!]
*
* However, Insert 2 did not actually insert a row.
*
* Tested with SQLite 3.6.11 [prepare_v2] and 3.1.3 [prepare]
*/
int main(int argc, char **argv){
sqlite3 *db;
sqlite3_stmt *s1 = NULL, *s2 = NULL;
char *zErrMsg = 0;
int rc;
if (argc != 2){
fprintf(stderr
, "usage: %s db\n", argv
[0]);
}
rc = sqlite3_open(argv[1], &db);
if( rc ){
fprintf(stderr
, "Can't open database: %s\n", sqlite3_errmsg
(db
));
sqlite3_close(db);
}
rc = sqlite3_prepare_v2(db, "INSERT into c(k,v) VALUES('d', 'e');",
-1, &s1, NULL);
if( rc!=SQLITE_OK ){
fprintf(stderr
, "SQL error %d: %s\n", rc
, sqlite3_errmsg
(db
));
goto end;
}
rc = sqlite3_prepare_v2(db, "INSERT into c(k,v) VALUES('f', 'g');",
-1, &s2, NULL);
if( rc!=SQLITE_OK ){
fprintf(stderr
, "SQL error %d: %s\n", rc
, sqlite3_errmsg
(db
));
goto end;
}
rc = sqlite3_step(s1);
if( rc!=SQLITE_DONE ){
fprintf(stderr
, "Insert 1 SQL error %d: %s\n", rc
, sqlite3_errmsg
(db
));
/* sqlite3_reset(s1); */ /* reset required on BUSY, or Insert 2 "succeeds" */
} else {
fprintf(stderr
, "Insert 1 succeeded, %d rows changed\n", sqlite3_changes
(db
));
}
rc = sqlite3_step(s2);
if( rc!=SQLITE_DONE ){
fprintf(stderr
, "Insert 2 SQL error %d: %s\n", rc
, sqlite3_errmsg
(db
));
} else {
fprintf(stderr
, "Insert 2 succeeded, %d rows changed\n", sqlite3_changes
(db
));
}
end:
if (s1) sqlite3_finalize(s1);
if (s2) sqlite3_finalize(s2);
sqlite3_close(db);
return 0;
}