出于安全考虑,我想在Python进程中禁用pickle.loads
。我想继续使用pickle.dumps
。
有没有标准的方法来实现这一目标?
要明确我并不担心我的用户是恶意的。但是我担心他们可能会无意中使用以意外方式触发pickle.loads
的库代码。
答案 0 :(得分:0)
我不了解标准方法,但根据您的使用情况,我想到的一个想法是覆盖该功能:
pickle.loads = '_disabled'
答案 1 :(得分:0)
我认为像pickle.loads = disabled
那样修补disabled
引发一些异常是最容易的。如果您真的担心在有机会清除它之前缓存该函数,可以使用以下内容直接修补函数指针:
#include <Python.h>
#include <methodobject.h>
/**
Patch the c implementation of a `builtin_function_or_method`.
@param ob The builtin_function_or_method object to patch.
@param new_meth The new C function pointer to use.
@param new_flags The new flags to set.
@param old_meth pointer to store the old function pointer in. If this
function fails, this value will be unchanged. If this value is `NULL`,
it will not be stored.
@param old_meth pointer to store the old function pointer in. If this
function fails, this value will be unchanged.
@param old_flags A pointer to store the old flags in. If this function fails,
this value will be unchanged. If this value is `NULL`, it will not be
stored.
@return zero if the method was patched succesfully, non-zero on failure. If
this function returns non-zero, an exception will be raised.
*/
static int patch_c_function(PyObject* ob,
PyCFunction new_meth,
int new_flags,
PyCFunction* old_meth,
int* old_flags) {
if (!PyCFunction_Check(ob)) {
PyErr_Format(PyExc_TypeError,
"expected builtin_function_or_method object, got: %s",
Py_TYPE(ob)->tp_name);
return -1;
}
PyCFunctionObject* function_object = (PyCFunctionObject*) ob;
if (old_meth) {
*old_meth = function_object->m_ml->ml_meth;
}
function_object->m_ml->ml_meth = new_meth;
if (old_flags) {
*old_flags = function_object->m_ml->ml_flags;
}
function_object->m_ml->ml_flags = new_flags;
return 0;
}
static PyObject* disabled(void) {
PyErr_SetString(PyExc_AssertionError,
"this function is disabled in this process");
return NULL;
}
static PyObject* disable_function(PyObject* self, PyObject* f) {
if (patch_c_function(f,
(PyCFunction) disabled,
METH_VARARGS | METH_KEYWORDS,
NULL,
NULL)) {
return NULL;
}
Py_RETURN_NONE;
}
PyMethodDef methods[] = {
{"disable_function", (PyCFunction) disable_function, METH_O, NULL},
{NULL},
};
PyModuleDef cext_module = {
PyModuleDef_HEAD_INIT,
"cext",
NULL,
-1,
methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit_cext(void) {
return PyModule_Create(&cext_module);
}
然后可以在以下的代码中使用:
In [1]: import pickle
In [2]: loads = pickle.loads
In [3]: from cext import disable_function
In [4]: disable_function(pickle.loads)
In [5]: pickle.loads()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-5-95a055f9ba4f> in <module>()
----> 1 pickle.loads()
AssertionError: this function is disabled in this process
In [6]: loads()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-6-73007b0e1946> in <module>()
----> 1 loads()
AssertionError: this function is disabled in this process