Skip to content

extmod/modbtree: Add checks for already-closed database. #12949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion extmod/modbtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ void __dbpanic(DB *db) {
mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db);
}

static void check_btree_is_open(mp_obj_btree_t *self) {
if (!self->db) {
mp_raise_ValueError(MP_ERROR_TEXT("database closed"));
}
}

static mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type);
o->stream = stream;
Expand All @@ -114,19 +120,28 @@ static void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind

static mp_obj_t btree_flush(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0));
}
static MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush);

static mp_obj_t btree_close(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(__bt_close(self->db));
int res;
if (self->db) {
res = __bt_close(self->db);
self->db = NULL;
} else {
res = RET_SUCCESS; // Closing an already-closed DB always succeeds.
}
return MP_OBJ_NEW_SMALL_INT(res);
}
static MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close);

static mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
DBT key, val;
buf_to_dbt(args[1], &key);
buf_to_dbt(args[2], &val);
Expand All @@ -136,6 +151,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);

static mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
DBT key, val;
buf_to_dbt(args[1], &key);
int res = __bt_get(self->db, &key, &val, 0);
Expand All @@ -153,6 +169,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_get_obj, 2, 3, btree_get);

static mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
DBT key, val;
if (n_args > 2) {
Expand Down Expand Up @@ -225,6 +242,7 @@ static mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {

static mp_obj_t btree_iternext(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
DBT key, val;
int res;
bool desc = self->flags & FLAG_DESC;
Expand Down Expand Up @@ -281,6 +299,7 @@ static mp_obj_t btree_iternext(mp_obj_t self_in) {

static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
if (value == MP_OBJ_NULL) {
// delete
DBT key;
Expand Down Expand Up @@ -314,6 +333,7 @@ static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {

static mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
check_btree_is_open(self);
switch (op) {
case MP_BINARY_OP_CONTAINS: {
DBT key, val;
Expand Down
39 changes: 39 additions & 0 deletions tests/extmod/btree_closed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
try:
import btree
import io
except ImportError:
print("SKIP")
raise SystemExit

f = io.BytesIO()
db = btree.open(f)

db[b"foo"] = b"42"

db.close()

# Accessing an already-closed database should fail.
try:
print(db[b"foo"])
except ValueError:
print("ValueError")

try:
db[b"bar"] = b"43"
except ValueError:
print("ValueError")

try:
db.flush()
except ValueError:
print("ValueError")

try:
for k, v in db.items():
pass
except ValueError:
print("ValueError")

# Closing and printing an already-closed database should not fail.
db.close()
print(db)
5 changes: 5 additions & 0 deletions tests/extmod/btree_closed.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ValueError
ValueError
ValueError
ValueError
<btree 0>
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy