Fix crash accessing the clipboard

The clipboard can change between checking it's length and
copying into the allocated buffer.

Move this from RNA to the C/Python API.
This commit is contained in:
Campbell Barton 2020-05-13 16:01:26 +10:00
parent 75d0287cee
commit 0e0ebdb65c
2 changed files with 45 additions and 39 deletions

View File

@ -1233,39 +1233,6 @@ static bool rna_KeyMapItem_userdefined_get(PointerRNA *ptr)
return kmi->id < 0;
}
static void rna_wmClipboard_get(PointerRNA *UNUSED(ptr), char *value)
{
char *pbuf;
int pbuf_len;
pbuf = WM_clipboard_text_get(false, &pbuf_len);
if (pbuf) {
memcpy(value, pbuf, pbuf_len + 1);
MEM_freeN(pbuf);
}
else {
value[0] = '\0';
}
}
static int rna_wmClipboard_length(PointerRNA *UNUSED(ptr))
{
char *pbuf;
int pbuf_len;
pbuf = WM_clipboard_text_get(false, &pbuf_len);
if (pbuf) {
MEM_freeN(pbuf);
}
return pbuf_len;
}
static void rna_wmClipboard_set(PointerRNA *UNUSED(ptr), const char *value)
{
WM_clipboard_text_set((void *)value, false);
}
static PointerRNA rna_WindowManager_xr_session_state_get(PointerRNA *ptr)
{
wmWindowManager *wm = ptr->data;
@ -2493,11 +2460,6 @@ static void rna_def_windowmanager(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Key Configurations", "Registered key configurations");
rna_def_wm_keyconfigs(brna, prop);
prop = RNA_def_property(srna, "clipboard", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(
prop, "rna_wmClipboard_get", "rna_wmClipboard_length", "rna_wmClipboard_set");
RNA_def_property_ui_text(prop, "Text Clipboard", "");
prop = RNA_def_property(srna, "xr_session_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "xr.session_settings");
RNA_def_property_flag(prop, PROP_NEVER_NULL);

View File

@ -45,6 +45,40 @@
#include "WM_api.h"
/* -------------------------------------------------------------------- */
/** \name Window Manager Clipboard Property
*
* Avoid using the RNA API because this value may change between checking it's length
* and creating the buffer, causing writes past the allocated length.
* \{ */
static PyObject *pyrna_WindowManager_clipboard_get(PyObject *UNUSED(self), void *UNUSED(flag))
{
int text_len = 0;
char *text = WM_clipboard_text_get(false, &text_len);
PyObject *result = PyC_UnicodeFromByteAndSize(text ? text : "", text_len);
if (text != NULL) {
MEM_freeN(text);
}
return result;
}
static int pyrna_WindowManager_clipboard_set(PyObject *UNUSED(self),
PyObject *value,
void *UNUSED(flag))
{
PyObject *value_coerce = NULL;
const char *text = PyC_UnicodeAsByte(value, &value_coerce);
if (text == NULL) {
return -1;
}
WM_clipboard_text_set(text, false);
Py_XDECREF(value_coerce);
return 0;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Window Manager Type
* \{ */
@ -61,6 +95,15 @@ static struct PyMethodDef pyrna_windowmanager_methods[] = {
{NULL, NULL, 0, NULL},
};
static struct PyGetSetDef pyrna_windowmanager_getset[] = {
{"clipboard",
pyrna_WindowManager_clipboard_get,
pyrna_WindowManager_clipboard_set,
NULL,
NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
/** \} */
/* -------------------------------------------------------------------- */
@ -122,7 +165,8 @@ static struct PyMethodDef pyrna_space_methods[] = {
void BPY_rna_types_extend_capi(void)
{
pyrna_struct_type_extend_capi(&RNA_Space, pyrna_space_methods, NULL);
pyrna_struct_type_extend_capi(&RNA_WindowManager, pyrna_windowmanager_methods, NULL);
pyrna_struct_type_extend_capi(
&RNA_WindowManager, pyrna_windowmanager_methods, pyrna_windowmanager_getset);
}
/** \} */