Skip to content

Commit f2603a8

Browse files
committed
Add regression tests for errmsg, bind after release, and deserialize database_name
Targets three issues found during PR review: - errmsg(conn) after close returns "out of memory" instead of an error tuple - errmsg(stmt) after release returns {:error, :connection_closed} instead of nil - bind/2 crashes with Protocol.UndefinedError when statement is released
1 parent 0a3ec20 commit f2603a8

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

test/exqlite/sqlite3_test.exs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ defmodule Exqlite.Sqlite3Test do
22
use ExUnit.Case
33

44
alias Exqlite.Sqlite3
5+
alias Exqlite.Sqlite3NIF
56
doctest Exqlite.Sqlite3
67

78
describe ".open/1" do
@@ -992,6 +993,44 @@ defmodule Exqlite.Sqlite3Test do
992993
assert {:error, _} = Sqlite3.set_update_hook(conn, self())
993994
end
994995
end
996+
997+
# Targets conn->db NULL dereference in exqlite_errmsg (connection branch).
998+
# After close(), conn->db is NULL. exqlite_errmsg calls
999+
# sqlite3_errmsg(conn->db) without a NULL guard → segfault.
1000+
test "errmsg conn after close does not segfault" do
1001+
for _ <- 1..50 do
1002+
{:ok, conn} = Sqlite3.open(":memory:")
1003+
:ok = Sqlite3.close(conn)
1004+
assert {:error, _} = Sqlite3NIF.errmsg(conn)
1005+
end
1006+
end
1007+
1008+
# Targets misleading return value in exqlite_errmsg (statement branch).
1009+
# After release(), statement->statement is NULL. The NIF should return
1010+
# nil (no error message available), not {:error, :connection_closed}.
1011+
test "errmsg stmt after release returns nil" do
1012+
for _ <- 1..50 do
1013+
{:ok, conn} = Sqlite3.open(":memory:")
1014+
{:ok, stmt} = Sqlite3.prepare(conn, "select 1")
1015+
:ok = Sqlite3.release(conn, stmt)
1016+
assert nil == Sqlite3NIF.errmsg(stmt)
1017+
:ok = Sqlite3.close(conn)
1018+
end
1019+
end
1020+
1021+
# Targets bind/2 crash when statement is released.
1022+
# bind_parameter_count returns {:error, :invalid_statement} after release,
1023+
# but bind/2 assumes it always returns an integer, causing a confusing
1024+
# crash instead of a clean error.
1025+
test "bind after release returns error" do
1026+
for _ <- 1..50 do
1027+
{:ok, conn} = Sqlite3.open(":memory:")
1028+
{:ok, stmt} = Sqlite3.prepare(conn, "select ?")
1029+
:ok = Sqlite3.release(conn, stmt)
1030+
assert {:error, :invalid_statement} = Sqlite3.bind(stmt, [42])
1031+
:ok = Sqlite3.close(conn)
1032+
end
1033+
end
9951034
end
9961035

9971036
describe ".step, .columns, .multi_step, .reset, .bind_* after release" do

0 commit comments

Comments
 (0)