Ref https://github.com/iustin/pylibacl/commit/65e6c78eb9338c8b3ac77b89880ca4f5f85d62b5 --- a/acl.c +++ b/acl.c @@ -90,12 +90,14 @@ typedef struct { typedef struct { PyObject_HEAD PyObject *parent_acl; /* The parent acl, so it won't run out on us */ + acl_t true_parent_acl; acl_entry_t entry; } Entry_Object; typedef struct { PyObject_HEAD PyObject *parent_entry; /* The parent entry, so it won't run out on us */ + acl_t true_parent_acl; acl_permset_t permset; } Permset_Object; @@ -231,10 +233,7 @@ static int ACL_init(PyObject* obj, PyObject* args, PyObject *keywds) { return -1; } - /* Free the old acl_t without checking for error, we don't - * care right now */ - if(self->acl != NULL) - acl_free(self->acl); + // May still have reference to self->acl. Don't free it since memory leak is better than UB self->acl = new; @@ -606,6 +605,7 @@ static PyObject* ACL_iternext(PyObject *obj) { the_entry_obj->entry = the_entry_t; the_entry_obj->parent_acl = obj; + the_entry_obj->true_parent_acl = self->acl; Py_INCREF(obj); /* For the reference we have in entry->parent */ return (PyObject*)the_entry_obj; @@ -635,9 +635,16 @@ static PyObject* ACL_delete_entry(PyObject *obj, PyObject *args) { "Can't remove un-owned entry"); return NULL; } + if (e->true_parent_acl != self->acl) { + PyErr_SetString(PyExc_ValueError, + "Can't remove entry after reinitialization"); + return NULL; + } if(acl_delete_entry(self->acl, e->entry) == -1) return PyErr_SetFromErrno(PyExc_IOError); + e->entry = NULL; + Py_RETURN_NONE; } @@ -799,6 +806,7 @@ static PyObject* Entry_new(PyTypeObject* type, PyObject* args, } Py_INCREF(parent); entry->parent_acl = (PyObject*)parent; + entry->true_parent_acl = parent->acl; return newentry; } @@ -815,6 +823,11 @@ static int Entry_init(PyObject* obj, PyObject* args, PyObject *keywds) { "Can't reinitialize with a different parent"); return -1; } + if ((PyObject*)parent != self->parent_acl) { + PyErr_SetString(PyExc_ValueError, + "Can't reinitialize with a reinitialized parent"); + return -1; + } return 0; }