pyntdb: Don't allow access after a database is closed.
authorJelmer Vernooij <jelmer@samba.org>
Sun, 1 Dec 2013 23:20:34 +0000 (23:20 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 6 Dec 2013 04:21:03 +0000 (05:21 +0100)
Signed-off-by: Jelmer Vernooij <jelmer@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/ntdb/pyntdb.c
lib/ntdb/wscript

index e4965fbae16c47c167abffc60bc8e36adec800bd..791ab93ae7a1f14ee017683cfa01b2aad0d7b619 100644 (file)
@@ -72,6 +72,14 @@ static PyObject *PyString_FromNtdb_Data(NTDB_DATA data)
                return NULL; \
        }
 
+#define PyNtdb_CHECK_CLOSED(pyobj) \
+       if (pyobj->closed) {\
+               PyErr_SetObject(PyExc_RuntimeError, \
+                       Py_BuildValue("(i,s)", NTDB_ERR_EINVAL, "database is closed")); \
+               return NULL; \
+       }
+
+
 static void stderr_log(struct ntdb_context *ntdb,
                       enum ntdb_log_level level,
                       enum NTDB_ERROR ecode,
@@ -120,53 +128,66 @@ static PyObject *py_ntdb_open(PyTypeObject *type, PyObject *args, PyObject *kwar
 
 static PyObject *obj_transaction_cancel(PyNtdbObject *self)
 {
+       PyNtdb_CHECK_CLOSED(self);
        ntdb_transaction_cancel(self->ctx);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_transaction_commit(PyNtdbObject *self)
 {
-       enum NTDB_ERROR ret = ntdb_transaction_commit(self->ctx);
+       enum NTDB_ERROR ret;
+       PyNtdb_CHECK_CLOSED(self);
+       ret = ntdb_transaction_commit(self->ctx);
        PyErr_NTDB_ERROR_IS_ERR_RAISE(ret);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_transaction_prepare_commit(PyNtdbObject *self)
 {
-       enum NTDB_ERROR ret = ntdb_transaction_prepare_commit(self->ctx);
+       enum NTDB_ERROR ret;
+       PyNtdb_CHECK_CLOSED(self);
+       ret = ntdb_transaction_prepare_commit(self->ctx);
        PyErr_NTDB_ERROR_IS_ERR_RAISE(ret);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_transaction_start(PyNtdbObject *self)
 {
-       enum NTDB_ERROR ret = ntdb_transaction_start(self->ctx);
+       enum NTDB_ERROR ret;
+       PyNtdb_CHECK_CLOSED(self);
+       ret = ntdb_transaction_start(self->ctx);
        PyErr_NTDB_ERROR_IS_ERR_RAISE(ret);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_lockall(PyNtdbObject *self)
 {
-       enum NTDB_ERROR ret = ntdb_lockall(self->ctx);
+       enum NTDB_ERROR ret;
+       PyNtdb_CHECK_CLOSED(self);
+       ret = ntdb_lockall(self->ctx);
        PyErr_NTDB_ERROR_IS_ERR_RAISE(ret);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_unlockall(PyNtdbObject *self)
 {
+       PyNtdb_CHECK_CLOSED(self);
        ntdb_unlockall(self->ctx);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_lockall_read(PyNtdbObject *self)
 {
-       enum NTDB_ERROR ret = ntdb_lockall_read(self->ctx);
+       enum NTDB_ERROR ret;
+       PyNtdb_CHECK_CLOSED(self);
+       ret = ntdb_lockall_read(self->ctx);
        PyErr_NTDB_ERROR_IS_ERR_RAISE(ret);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_unlockall_read(PyNtdbObject *self)
 {
+       PyNtdb_CHECK_CLOSED(self);
        ntdb_unlockall_read(self->ctx);
        Py_RETURN_NONE;
 }
@@ -190,6 +211,9 @@ static PyObject *obj_get(PyNtdbObject *self, PyObject *args)
        NTDB_DATA key, data;
        PyObject *py_key;
        enum NTDB_ERROR ret;
+
+       PyNtdb_CHECK_CLOSED(self);
+
        if (!PyArg_ParseTuple(args, "O", &py_key))
                return NULL;
 
@@ -206,6 +230,9 @@ static PyObject *obj_append(PyNtdbObject *self, PyObject *args)
        NTDB_DATA key, data;
        PyObject *py_key, *py_data;
        enum NTDB_ERROR ret;
+
+       PyNtdb_CHECK_CLOSED(self);
+
        if (!PyArg_ParseTuple(args, "OO", &py_key, &py_data))
                return NULL;
 
@@ -222,6 +249,8 @@ static PyObject *obj_firstkey(PyNtdbObject *self)
        enum NTDB_ERROR ret;
        NTDB_DATA key;
 
+       PyNtdb_CHECK_CLOSED(self);
+
        ret = ntdb_firstkey(self->ctx, &key);
        if (ret == NTDB_ERR_NOEXIST)
                Py_RETURN_NONE;
@@ -235,6 +264,9 @@ static PyObject *obj_nextkey(PyNtdbObject *self, PyObject *args)
        NTDB_DATA key;
        PyObject *py_key;
        enum NTDB_ERROR ret;
+
+       PyNtdb_CHECK_CLOSED(self);
+
        if (!PyArg_ParseTuple(args, "O", &py_key))
                return NULL;
 
@@ -256,6 +288,9 @@ static PyObject *obj_delete(PyNtdbObject *self, PyObject *args)
        NTDB_DATA key;
        PyObject *py_key;
        enum NTDB_ERROR ret;
+
+       PyNtdb_CHECK_CLOSED(self);
+
        if (!PyArg_ParseTuple(args, "O", &py_key))
                return NULL;
 
@@ -269,6 +304,9 @@ static PyObject *obj_has_key(PyNtdbObject *self, PyObject *args)
 {
        NTDB_DATA key;
        PyObject *py_key;
+
+       PyNtdb_CHECK_CLOSED(self);
+
        if (!PyArg_ParseTuple(args, "O", &py_key))
                return NULL;
 
@@ -284,6 +322,7 @@ static PyObject *obj_store(PyNtdbObject *self, PyObject *args)
        enum NTDB_ERROR ret;
        int flag = NTDB_REPLACE;
        PyObject *py_key, *py_value;
+       PyNtdb_CHECK_CLOSED(self);
 
        if (!PyArg_ParseTuple(args, "OO|i", &py_key, &py_value, &flag))
                return NULL;
@@ -299,6 +338,7 @@ static PyObject *obj_store(PyNtdbObject *self, PyObject *args)
 static PyObject *obj_add_flag(PyNtdbObject *self, PyObject *args)
 {
        unsigned flag;
+       PyNtdb_CHECK_CLOSED(self);
 
        if (!PyArg_ParseTuple(args, "I", &flag))
                return NULL;
@@ -311,6 +351,8 @@ static PyObject *obj_remove_flag(PyNtdbObject *self, PyObject *args)
 {
        unsigned flag;
 
+       PyNtdb_CHECK_CLOSED(self);
+
        if (!PyArg_ParseTuple(args, "I", &flag))
                return NULL;
 
@@ -360,6 +402,7 @@ static PyObject *ntdb_object_iter(PyNtdbObject *self)
 {
        PyNtdbIteratorObject *ret;
        enum NTDB_ERROR e;
+       PyNtdb_CHECK_CLOSED(self);
 
        ret = PyObject_New(PyNtdbIteratorObject, &PyNtdbIterator);
        if (!ret)
@@ -378,13 +421,16 @@ static PyObject *ntdb_object_iter(PyNtdbObject *self)
 
 static PyObject *obj_clear(PyNtdbObject *self)
 {
-       enum NTDB_ERROR ret = ntdb_wipe_all(self->ctx);
+       enum NTDB_ERROR ret;
+       PyNtdb_CHECK_CLOSED(self);
+       ret = ntdb_wipe_all(self->ctx);
        PyErr_NTDB_ERROR_IS_ERR_RAISE(ret);
        Py_RETURN_NONE;
 }
 
 static PyObject *obj_enable_seqnum(PyNtdbObject *self)
 {
+       PyNtdb_CHECK_CLOSED(self);
        ntdb_add_flag(self->ctx, NTDB_SEQNUM);
        Py_RETURN_NONE;
 }
@@ -433,16 +479,19 @@ static PyMethodDef ntdb_object_methods[] = {
 
 static PyObject *obj_get_flags(PyNtdbObject *self, void *closure)
 {
+       PyNtdb_CHECK_CLOSED(self);
        return PyInt_FromLong(ntdb_get_flags(self->ctx));
 }
 
 static PyObject *obj_get_filename(PyNtdbObject *self, void *closure)
 {
+       PyNtdb_CHECK_CLOSED(self);
        return PyString_FromString(ntdb_name(self->ctx));
 }
 
 static PyObject *obj_get_seqnum(PyNtdbObject *self, void *closure)
 {
+       PyNtdb_CHECK_CLOSED(self);
        return PyInt_FromLong(ntdb_get_seqnum(self->ctx));
 }
 
@@ -476,6 +525,8 @@ static PyObject *obj_getitem(PyNtdbObject *self, PyObject *key)
        NTDB_DATA tkey, val;
        enum NTDB_ERROR ret;
 
+       PyNtdb_CHECK_CLOSED(self);
+
        if (!PyString_Check(key)) {
                PyErr_SetString(PyExc_TypeError, "Expected string as key");
                return NULL;
@@ -498,6 +549,12 @@ static int obj_setitem(PyNtdbObject *self, PyObject *key, PyObject *value)
 {
        NTDB_DATA tkey, tval;
        enum NTDB_ERROR ret;
+       if (self->closed) {
+               PyErr_SetObject(PyExc_RuntimeError,
+                       Py_BuildValue("(i,s)", NTDB_ERR_EINVAL, "database is closed"));
+               return -1;
+       }
+
        if (!PyString_Check(key)) {
                PyErr_SetString(PyExc_TypeError, "Expected string as key");
                return -1;
@@ -530,6 +587,7 @@ static PyMappingMethods ntdb_object_mapping = {
        .mp_subscript = (binaryfunc)obj_getitem,
        .mp_ass_subscript = (objobjargproc)obj_setitem,
 };
+
 static PyTypeObject PyNtdb = {
        .tp_name = "ntdb.Ntdb",
        .tp_basicsize = sizeof(PyNtdbObject),
index de67615446065da94e16d167ebb97d46abea7e7b..d4828b02fb0cd5269a0b15d351928d01d3af0586 100644 (file)
@@ -92,6 +92,7 @@ def configure(conf):
                                 'test/api-record-expand.c',
                                 'test/api-simple-delete.c',
                                 'test/api-summary.c']
+    conf.env.NTDB_TEST_API_PY=['test/python-api.py']
     conf.env.NTDB_TEST_API_HELPER_SRC=['test/helpapi-external-agent.c']
     conf.env.NTDB_TEST_RUN_HELPER_SRC=['test/helprun-external-agent.c',
                                        'test/helprun-layout.c']
@@ -253,6 +254,18 @@ def testonly(ctx):
                 samba_utils.RUN_COMMAND("cat " + os.path.join(testdir, 'test-output'))
                 ecode = ret;
                 break;
+        if not env.disable_python:
+            for f in env.NTDB_TEST_API_PY:
+                print("..." + f)
+                cmd = "cd " + testdir + " && PYTHONPATH=%s %s %s" % (
+                    os.path.abspath(os.path.join(Utils.g_module.blddir, "python")),
+                        env["PYTHON"], os.path.abspath(f))
+                print cmd
+                ret = samba_utils.RUN_COMMAND(cmd)
+                if ret != 0:
+                    print("%s (%s) failed:" % (name, f))
+                    ecode = ret
+                    break
 
     sys.exit(ecode)