Skip to content

Commit f833c8f

Browse files
committed
Take read lock before checking if closed
This prevents a race in ReaderIter_next and protects against writes that are not atomic for the others.
1 parent 2f45722 commit f833c8f

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

extension/maxminddb.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -641,12 +641,19 @@ static PyObject *Reader_close(PyObject *self, PyObject *UNUSED(args)) {
641641
static PyObject *Reader__enter__(PyObject *self, PyObject *UNUSED(args)) {
642642
Reader_obj *mmdb_obj = (Reader_obj *)self;
643643

644+
if (reader_acquire_read_lock(mmdb_obj) != 0) {
645+
return NULL;
646+
}
647+
644648
if (mmdb_obj->closed == Py_True) {
649+
reader_release_read_lock(mmdb_obj);
645650
PyErr_SetString(PyExc_ValueError,
646651
"Attempt to reopen a closed MaxMind DB.");
647652
return NULL;
648653
}
649654

655+
reader_release_read_lock(mmdb_obj);
656+
650657
Py_INCREF(self);
651658
return (PyObject *)self;
652659
}
@@ -669,12 +676,20 @@ static void Reader_dealloc(PyObject *self) {
669676

670677
static PyObject *Reader_iter(PyObject *obj) {
671678
Reader_obj *reader = (Reader_obj *)obj;
679+
680+
if (reader_acquire_read_lock(reader) != 0) {
681+
return NULL;
682+
}
683+
672684
if (reader->closed == Py_True) {
685+
reader_release_read_lock(reader);
673686
PyErr_SetString(PyExc_ValueError,
674687
"Attempt to iterate over a closed MaxMind DB.");
675688
return NULL;
676689
}
677690

691+
reader_release_read_lock(reader);
692+
678693
ReaderIter_obj *ri = PyObject_New(ReaderIter_obj, &ReaderIter_Type);
679694
if (ri == NULL) {
680695
return NULL;
@@ -705,13 +720,15 @@ static bool is_ipv6(char ip[16]) {
705720

706721
static PyObject *ReaderIter_next(PyObject *self) {
707722
ReaderIter_obj *ri = (ReaderIter_obj *)self;
708-
if (ri->reader->closed == Py_True) {
709-
PyErr_SetString(PyExc_ValueError,
710-
"Attempt to iterate over a closed MaxMind DB.");
723+
724+
if (reader_acquire_read_lock(ri->reader) != 0) {
711725
return NULL;
712726
}
713727

714-
if (reader_acquire_read_lock(ri->reader) != 0) {
728+
if (ri->reader->closed == Py_True) {
729+
reader_release_read_lock(ri->reader);
730+
PyErr_SetString(PyExc_ValueError,
731+
"Attempt to iterate over a closed MaxMind DB.");
715732
return NULL;
716733
}
717734

0 commit comments

Comments
 (0)