plugins/python/pyhelpers: add helpers for attribute handling

to simplify code a bit.
This commit is contained in:
Robert Manner
2020-01-31 09:45:16 +01:00
committed by Todd C. Miller
parent 4110800c14
commit 62524416eb
3 changed files with 87 additions and 52 deletions

View File

@@ -143,7 +143,7 @@ py_log_last_error(const char *context_message)
debug_return; debug_return;
} }
PyObject *py_type, *py_message, *py_traceback; PyObject *py_type = NULL, *py_message = NULL, *py_traceback = NULL;
PyErr_Fetch(&py_type, &py_message, &py_traceback); PyErr_Fetch(&py_type, &py_message, &py_traceback);
char *message = py_message ? py_create_string_rep(py_message) : strdup("(NULL)"); char *message = py_message ? py_create_string_rep(py_message) : strdup("(NULL)");
@@ -398,7 +398,7 @@ py_get_current_execution_frame(char **file_name, long *line_number, char **funct
PyObject *py_err_type = NULL, *py_err_value = NULL, *py_err_traceback = NULL; PyObject *py_err_type = NULL, *py_err_value = NULL, *py_err_traceback = NULL;
PyErr_Fetch(&py_err_type, &py_err_value, &py_err_traceback); PyErr_Fetch(&py_err_type, &py_err_value, &py_err_traceback);
PyObject *py_frame = NULL, *py_lineno = NULL, *py_f_code = NULL, PyObject *py_frame = NULL, *py_f_code = NULL,
*py_filename = NULL, *py_function_name = NULL; *py_filename = NULL, *py_function_name = NULL;
PyObject *py_getframe = PySys_GetObject("_getframe"); PyObject *py_getframe = PySys_GetObject("_getframe");
@@ -409,25 +409,21 @@ py_get_current_execution_frame(char **file_name, long *line_number, char **funct
if (py_frame == NULL) if (py_frame == NULL)
goto cleanup; goto cleanup;
py_lineno = PyObject_GetAttrString(py_frame, "f_lineno"); *line_number = py_object_get_optional_attr_number(py_frame, "f_lineno");
if (py_lineno != NULL) {
*line_number = PyLong_AsLong(py_lineno);
}
py_f_code = PyObject_GetAttrString(py_frame, "f_code"); py_f_code = py_object_get_optional_attr(py_frame, "f_code", NULL);
if (py_f_code != NULL) { if (py_f_code != NULL) {
py_filename = PyObject_GetAttrString(py_f_code, "co_filename"); py_filename = py_object_get_optional_attr(py_f_code, "co_filename", NULL);
if (py_filename != NULL) if (py_filename != NULL)
*file_name = strdup(PyUnicode_AsUTF8(py_filename)); *file_name = strdup(PyUnicode_AsUTF8(py_filename));
py_function_name = PyObject_GetAttrString(py_f_code, "co_name"); py_function_name = py_object_get_optional_attr(py_f_code, "co_name", NULL);
if (py_function_name != NULL) if (py_function_name != NULL)
*function_name = strdup(PyUnicode_AsUTF8(py_function_name)); *function_name = strdup(PyUnicode_AsUTF8(py_function_name));
} }
cleanup: cleanup:
Py_CLEAR(py_frame); Py_CLEAR(py_frame);
Py_CLEAR(py_lineno);
Py_CLEAR(py_f_code); Py_CLEAR(py_f_code);
Py_CLEAR(py_filename); Py_CLEAR(py_filename);
Py_CLEAR(py_function_name); Py_CLEAR(py_function_name);
@@ -447,7 +443,8 @@ py_ctx_reset()
} }
int int
py_sudo_conv(int num_msgs, const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[], struct sudo_conv_callback *callback) py_sudo_conv(int num_msgs, const struct sudo_conv_message msgs[],
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
{ {
/* Enable suspend during password entry. */ /* Enable suspend during password entry. */
struct sigaction sa, saved_sigtstp; struct sigaction sa, saved_sigtstp;
@@ -465,3 +462,59 @@ py_sudo_conv(int num_msgs, const struct sudo_conv_message msgs[], struct sudo_co
return rc; return rc;
} }
PyObject *
py_object_get_optional_attr(PyObject *py_object, const char *attr, PyObject *py_default)
{
if (PyObject_HasAttrString(py_object, attr)) {
return PyObject_GetAttrString(py_object, attr);
}
Py_XINCREF(py_default); // whatever we return will have its refcount incremented
return py_default;
}
const char *
py_object_get_optional_attr_string(PyObject *py_object, const char *attr_name)
{
PyObject *py_value = py_object_get_optional_attr(py_object, attr_name, NULL);
if (py_value == NULL)
return NULL;
const char *value = PyUnicode_AsUTF8(py_value);
Py_CLEAR(py_value); // Note, the object still has reference to the attribute
return value;
}
long long
py_object_get_optional_attr_number(PyObject *py_object, const char *attr_name)
{
PyObject *py_value = py_object_get_optional_attr(py_object, attr_name, NULL);
if (py_value == NULL)
return -1;
long long value = PyLong_AsLongLong(py_value);
Py_CLEAR(py_value);
return value;
}
void
py_object_set_attr_number(PyObject *py_object, const char *attr_name, long long number)
{
PyObject *py_number = PyLong_FromLong(number);
if (py_number == NULL)
return;
PyObject_SetAttrString(py_object, attr_name, py_number);
Py_CLEAR(py_number);
}
void
py_object_set_attr_string(PyObject *py_object, const char *attr_name, const char *value)
{
PyObject *py_value = PyUnicode_FromString(value);
if (py_value == NULL)
return;
PyObject_SetAttrString(py_object, attr_name, py_value);
Py_CLEAR(py_value);
}

View File

@@ -71,6 +71,13 @@ char **py_str_array_from_tuple(PyObject *py_tuple);
CPYCHECKER_RETURNS_BORROWED_REF CPYCHECKER_RETURNS_BORROWED_REF
PyObject *py_tuple_get(PyObject *py_tuple, Py_ssize_t index, PyTypeObject *expected_type); PyObject *py_tuple_get(PyObject *py_tuple, Py_ssize_t index, PyTypeObject *expected_type);
PyObject *py_object_get_optional_attr(PyObject *py_object, const char *attr, PyObject *py_default);
long long py_object_get_optional_attr_number(PyObject *py_object, const char *attr_name);
const char *py_object_get_optional_attr_string(PyObject *py_object, const char *attr_name);
void py_object_set_attr_number(PyObject *py_object, const char *attr_name, long long number);
void py_object_set_attr_string(PyObject *py_object, const char *attr_name, const char *value);
PyObject *py_create_version(unsigned int version); PyObject *py_create_version(unsigned int version);
void py_debug_python_call(const char *class_name, const char *function_name, void py_debug_python_call(const char *class_name, const char *function_name,

View File

@@ -35,7 +35,6 @@ _sudo_ConvMessage__Init(PyObject *py_self, PyObject *py_args, PyObject *py_kwarg
PyObject *py_empty = PyTuple_New(0); PyObject *py_empty = PyTuple_New(0);
struct sudo_conv_message conv_message = { 0, 0, NULL }; struct sudo_conv_message conv_message = { 0, 0, NULL };
PyObject *py_msg_type = NULL, *py_timeout = NULL, *py_msg = NULL; // borrowed references
static char *keywords[] = { "self", "msg_type", "msg", "timeout", NULL }; static char *keywords[] = { "self", "msg_type", "msg", "timeout", NULL };
if (!PyArg_ParseTupleAndKeywords(py_args ? py_args : py_empty, py_kwargs, "Ois|i:sudo.ConvMessage", keywords, if (!PyArg_ParseTupleAndKeywords(py_args ? py_args : py_empty, py_kwargs, "Ois|i:sudo.ConvMessage", keywords,
@@ -46,31 +45,19 @@ _sudo_ConvMessage__Init(PyObject *py_self, PyObject *py_args, PyObject *py_kwarg
sudo_debug_printf(SUDO_DEBUG_TRACE, "Parsed arguments: self='%p' msg_type='%d' timeout='%d' msg='%s'", sudo_debug_printf(SUDO_DEBUG_TRACE, "Parsed arguments: self='%p' msg_type='%d' timeout='%d' msg='%s'",
(void *)py_self, conv_message.msg_type, conv_message.timeout, conv_message.msg); (void *)py_self, conv_message.msg_type, conv_message.timeout, conv_message.msg);
py_msg_type = PyLong_FromLong(conv_message.msg_type); py_object_set_attr_number(py_self, "msg_type", conv_message.msg_type);
if (py_msg_type == NULL) if (PyErr_Occurred())
goto cleanup; goto cleanup;
py_timeout = PyLong_FromLong(conv_message.timeout); py_object_set_attr_number(py_self, "timeout", conv_message.timeout);
if (py_timeout == NULL) if (PyErr_Occurred())
goto cleanup; goto cleanup;
py_msg = PyUnicode_FromString(conv_message.msg); py_object_set_attr_string(py_self, "msg", conv_message.msg);
if (py_msg == NULL) if (PyErr_Occurred())
goto cleanup;
if (PyObject_SetAttrString(py_self, "msg_type", py_msg_type) != 0)
goto cleanup;
if (PyObject_SetAttrString(py_self, "timeout", py_timeout) != 0)
goto cleanup;
if (PyObject_SetAttrString(py_self, "msg", py_msg) != 0)
goto cleanup; goto cleanup;
cleanup: cleanup:
Py_CLEAR(py_msg_type);
Py_CLEAR(py_timeout);
Py_CLEAR(py_msg);
Py_CLEAR(py_empty); Py_CLEAR(py_empty);
if (PyErr_Occurred()) if (PyErr_Occurred())
@@ -121,31 +108,19 @@ sudo_module_ConvMessage_to_c(PyObject *py_conv_message, struct sudo_conv_message
{ {
debug_decl(sudo_module_ConvMessage_to_c, PYTHON_DEBUG_C_CALLS); debug_decl(sudo_module_ConvMessage_to_c, PYTHON_DEBUG_C_CALLS);
int rc = SUDO_RC_ERROR; conv_message->msg_type = (int)py_object_get_optional_attr_number(py_conv_message, "msg_type");
PyObject *py_msg_type = NULL, *py_timeout = NULL, *py_msg = NULL; if (PyErr_Occurred())
debug_return_int(SUDO_RC_ERROR);
if ((py_msg_type = PyObject_GetAttrString(py_conv_message, "msg_type")) == NULL) conv_message->timeout = (int)py_object_get_optional_attr_number(py_conv_message, "timeout");
goto cleanup; if (PyErr_Occurred())
conv_message->msg_type = (int)PyLong_AsLong(py_msg_type); debug_return_int(SUDO_RC_ERROR);
if ((py_timeout = PyObject_GetAttrString(py_conv_message, "timeout")) == NULL) conv_message->msg = py_object_get_optional_attr_string(py_conv_message, "msg");
goto cleanup; if (PyErr_Occurred())
conv_message->timeout = (int)PyLong_AsLong(py_timeout); debug_return_int(SUDO_RC_ERROR);
if ((py_msg = PyObject_GetAttrString(py_conv_message, "msg")) == NULL) debug_return_int(SUDO_RC_OK);
goto cleanup;
conv_message->msg = PyUnicode_AsUTF8(py_msg);
if (conv_message->msg == NULL)
goto cleanup;
rc = SUDO_RC_OK;
cleanup:
Py_CLEAR(py_msg_type);
Py_CLEAR(py_timeout);
Py_CLEAR(py_msg);
debug_return_int(rc);
} }
int int