Fix #126156: Do not allow to assign embedded IDs to IDProperties.

This is just not supported, and typically not doable from Blender UI
(since embedded IDs won't be listed in ID template list).

Add asserts to IDProp code itself, and checks & error reports in
relevant BPY and RNA setters.
This commit is contained in:
Bastien Montagne
2024-08-21 18:16:59 +02:00
parent 08d5eb8f9c
commit de47fee2e1
4 changed files with 40 additions and 33 deletions

View File

@@ -536,6 +536,8 @@ static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag)
void IDP_AssignID(IDProperty *prop, ID *id, const int flag)
{
BLI_assert(prop->type == IDP_ID);
/* Do not assign embedded IDs to IDProperties. */
BLI_assert(!id || (id->flag & ID_FLAG_EMBEDDED_DATA) == 0);
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && IDP_Id(prop) != nullptr) {
id_us_min(IDP_Id(prop));

View File

@@ -66,6 +66,9 @@ std::unique_ptr<IDProperty, IDPropertyDeleter> create(const StringRefNull prop_n
ID *value,
const eIDPropertyFlag flags)
{
/* Do not assign embedded IDs to IDProperties. */
BLI_assert(!value || (value->flag & ID_FLAG_EMBEDDED_DATA) == 0);
IDPropertyTemplate prop_template{0};
prop_template.id = value;
IDProperty *property = IDP_New(IDP_ID, &prop_template, prop_name.c_str(), flags);

View File

@@ -3939,9 +3939,9 @@ void RNA_property_pointer_set(PointerRNA *ptr,
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_POINTER);
/* Check types. */
if (pprop->set != nullptr) {
/* Assigning to a real RNA property. */
/* This is a 'real' RNA property, not an IDProperty or a dynamic RNA property using an IDProperty
* as backend storage. */
if (pprop->set) {
if (ptr_value.type != nullptr && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
BKE_reportf(reports,
RPT_ERROR,
@@ -3951,17 +3951,25 @@ void RNA_property_pointer_set(PointerRNA *ptr,
ptr_value.type->identifier);
return;
}
}
else {
/* Assigning to an IDProperty disguised as RNA one. */
if (ptr_value.type != nullptr && !RNA_struct_is_a(ptr_value.type, &RNA_ID)) {
BKE_reportf(reports,
RPT_ERROR,
"%s: expected ID type, not %s",
__func__,
ptr_value.type->identifier);
return;
if (!((prop->flag & PROP_NEVER_NULL) && ptr_value.data == nullptr) &&
!((prop->flag & PROP_ID_SELF_CHECK) && ptr->owner_id == ptr_value.owner_id))
{
pprop->set(ptr, ptr_value, reports);
}
return;
}
/* Assigning to an IDProperty. */
ID *value = static_cast<ID *>(ptr_value.data);
if (ptr_value.type != nullptr && !RNA_struct_is_a(ptr_value.type, &RNA_ID)) {
BKE_reportf(
reports, RPT_ERROR, "%s: expected ID type, not %s", __func__, ptr_value.type->identifier);
return;
}
if (value && (value->flag & ID_FLAG_EMBEDDED_DATA) != 0) {
BKE_reportf(reports, RPT_ERROR, "%s: cannot assign an embedded ID to an IDProperty", __func__);
return;
}
/* We got an existing IDProperty. */
@@ -3970,7 +3978,7 @@ void RNA_property_pointer_set(PointerRNA *ptr,
* XXX This has to be investigated fully - there might be a good reason for it, but off hands
* this seems really weird... */
if (idprop->type == IDP_ID) {
IDP_AssignID(idprop, static_cast<ID *>(ptr_value.data), 0);
IDP_AssignID(idprop, value, 0);
rna_idproperty_touch(idprop);
}
else {
@@ -3978,30 +3986,18 @@ void RNA_property_pointer_set(PointerRNA *ptr,
IDProperty *group = RNA_struct_idprops(ptr, true);
BLI_assert(group != nullptr);
IDP_ReplaceInGroup_ex(group,
blender::bke::idprop::create(idprop->name,
static_cast<ID *>(ptr_value.data),
IDP_FLAG_STATIC_TYPE)
.release(),
idprop);
}
}
/* RNA property. */
else if (pprop->set) {
if (!((prop->flag & PROP_NEVER_NULL) && ptr_value.data == nullptr) &&
!((prop->flag & PROP_ID_SELF_CHECK) && ptr->owner_id == ptr_value.owner_id))
{
pprop->set(ptr, ptr_value, reports);
IDP_ReplaceInGroup_ex(
group,
blender::bke::idprop::create(idprop->name, value, IDP_FLAG_STATIC_TYPE).release(),
idprop);
}
}
/* IDProperty disguised as RNA property (and not yet defined in ptr). */
else if (prop->flag & PROP_EDITABLE) {
if (IDProperty *group = RNA_struct_idprops(ptr, true)) {
IDP_ReplaceInGroup(group,
blender::bke::idprop::create(prop->identifier,
static_cast<ID *>(ptr_value.data),
IDP_FLAG_STATIC_TYPE)
.release());
IDP_ReplaceInGroup(
group,
blender::bke::idprop::create(prop->identifier, value, IDP_FLAG_STATIC_TYPE).release());
}
}
}

View File

@@ -980,6 +980,12 @@ static IDProperty *idp_from_DatablockPointer(IDProperty *prop_exist,
IDProperty *prop = nullptr;
ID *value = nullptr;
pyrna_id_FromPyObject(ob, &value);
if (value && (value->flag & ID_FLAG_EMBEDDED_DATA) != 0) {
PyErr_SetString(PyExc_ValueError, "Cannot assign an embedded ID pointer to an id-property");
return nullptr;
}
if (prop_exist) {
if (prop_exist->type == IDP_ID) {
IDP_AssignID(prop_exist, value, 0);