Skip to content

Commit 0631339

Browse files
committed
Add NULL guards in 12 statement functions after release
After Sqlite3.release(conn, stmt) sets statement->statement = NULL (under the connection lock), these functions dereference the NULL pointer, causing crashes or returning wrong results: - exqlite_reset, exqlite_bind_parameter_count, exqlite_bind_parameter_index, exqlite_bind_text, exqlite_bind_blob, exqlite_bind_integer, exqlite_bind_float, exqlite_bind_null: SQLite bind/reset functions called with NULL statement - exqlite_columns: sqlite3_column_count(NULL) returns 0, so columns/2 returns {:ok, []} instead of {:error, _} (confirmed test failure) - exqlite_step: sqlite3_step(NULL) returns SQLITE_MISUSE internally, but the guard makes the behaviour explicit - exqlite_multi_step: adds a second NULL guard after acquiring the connection lock, closing the TOCTOU window between the pre-lock check and the sqlite3_step() call - exqlite_errmsg (statement path): sqlite3_db_handle(NULL) Fix: in each function, after acquiring the statement/connection lock, check statement->statement == NULL and return {:error, :connection_closed}.
1 parent d732338 commit 0631339

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

c_src/sqlite3_nif.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,10 @@ exqlite_reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
543543
}
544544

545545
statement_acquire_lock(statement);
546+
if (statement->statement == NULL) {
547+
statement_release_lock(statement);
548+
return make_error_tuple(env, am_connection_closed);
549+
}
546550
sqlite3_reset(statement->statement);
547551
statement_release_lock(statement);
548552
return am_ok;
@@ -560,6 +564,10 @@ exqlite_bind_parameter_count(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
560564
}
561565

562566
statement_acquire_lock(statement);
567+
if (statement->statement == NULL) {
568+
statement_release_lock(statement);
569+
return make_error_tuple(env, am_connection_closed);
570+
}
563571
int bind_parameter_count = sqlite3_bind_parameter_count(statement->statement);
564572
statement_release_lock(statement);
565573
return enif_make_int(env, bind_parameter_count);
@@ -584,6 +592,10 @@ exqlite_bind_parameter_index(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
584592
}
585593

586594
statement_acquire_lock(statement);
595+
if (statement->statement == NULL) {
596+
statement_release_lock(statement);
597+
return make_error_tuple(env, am_connection_closed);
598+
}
587599
int index = sqlite3_bind_parameter_index(statement->statement, (const char*)name.data);
588600
statement_release_lock(statement);
589601
return enif_make_int(env, index);
@@ -611,6 +623,10 @@ exqlite_bind_text(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
611623
}
612624

613625
statement_acquire_lock(statement);
626+
if (statement->statement == NULL) {
627+
statement_release_lock(statement);
628+
return make_error_tuple(env, am_connection_closed);
629+
}
614630
int rc = sqlite3_bind_text(statement->statement, idx, (char*)text.data, text.size, SQLITE_TRANSIENT);
615631
statement_release_lock(statement);
616632
return enif_make_int(env, rc);
@@ -638,6 +654,10 @@ exqlite_bind_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
638654
}
639655

640656
statement_acquire_lock(statement);
657+
if (statement->statement == NULL) {
658+
statement_release_lock(statement);
659+
return make_error_tuple(env, am_connection_closed);
660+
}
641661
int rc = sqlite3_bind_blob(statement->statement, idx, (char*)blob.data, blob.size, SQLITE_TRANSIENT);
642662
statement_release_lock(statement);
643663
return enif_make_int(env, rc);
@@ -665,6 +685,10 @@ exqlite_bind_integer(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
665685
}
666686

667687
statement_acquire_lock(statement);
688+
if (statement->statement == NULL) {
689+
statement_release_lock(statement);
690+
return make_error_tuple(env, am_connection_closed);
691+
}
668692
int rc = sqlite3_bind_int64(statement->statement, idx, i);
669693
statement_release_lock(statement);
670694
return enif_make_int(env, rc);
@@ -692,6 +716,10 @@ exqlite_bind_float(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
692716
}
693717

694718
statement_acquire_lock(statement);
719+
if (statement->statement == NULL) {
720+
statement_release_lock(statement);
721+
return make_error_tuple(env, am_connection_closed);
722+
}
695723
int rc = sqlite3_bind_double(statement->statement, idx, f);
696724
statement_release_lock(statement);
697725
return enif_make_int(env, rc);
@@ -714,6 +742,10 @@ exqlite_bind_null(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
714742
}
715743

716744
statement_acquire_lock(statement);
745+
if (statement->statement == NULL) {
746+
statement_release_lock(statement);
747+
return make_error_tuple(env, am_connection_closed);
748+
}
717749
int rc = sqlite3_bind_null(statement->statement, idx);
718750
statement_release_lock(statement);
719751
return enif_make_int(env, rc);
@@ -760,6 +792,17 @@ exqlite_multi_step(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
760792

761793
connection_acquire_lock(conn);
762794

795+
if (conn->db == NULL) {
796+
connection_release_lock(conn);
797+
return make_error_tuple(env, am_connection_closed);
798+
}
799+
800+
if (statement->statement == NULL) {
801+
connection_release_lock(conn);
802+
return make_error_tuple(env, am_connection_closed);
803+
}
804+
805+
763806
ERL_NIF_TERM rows = enif_make_list_from_array(env, NULL, 0);
764807
for (int i = 0; i < chunk_size; i++) {
765808
ERL_NIF_TERM row;
@@ -821,6 +864,11 @@ exqlite_step(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
821864

822865
connection_acquire_lock(conn);
823866

867+
if (statement->statement == NULL) {
868+
connection_release_lock(conn);
869+
return make_error_tuple(env, am_connection_closed);
870+
}
871+
824872
int rc = sqlite3_step(statement->statement);
825873
switch (rc) {
826874
case SQLITE_ROW:
@@ -870,6 +918,10 @@ exqlite_columns(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
870918
}
871919

872920
statement_acquire_lock(statement);
921+
if (statement->statement == NULL) {
922+
statement_release_lock(statement);
923+
return make_error_tuple(env, am_connection_closed);
924+
}
873925
size = sqlite3_column_count(statement->statement);
874926

875927
if (size == 0) {
@@ -1454,6 +1506,10 @@ exqlite_errmsg(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
14541506
connection_release_lock(conn);
14551507
} else if (enif_get_resource(env, argv[0], statement_type, (void**)&statement)) {
14561508
statement_acquire_lock(statement);
1509+
if (statement->statement == NULL) {
1510+
statement_release_lock(statement);
1511+
return make_error_tuple(env, am_connection_closed);
1512+
}
14571513
msg = sqlite3_errmsg(sqlite3_db_handle(statement->statement));
14581514
statement_release_lock(statement);
14591515
} else {

0 commit comments

Comments
 (0)