UI: Include button type in button comparisons to preserve UI state

Only consider buttons with matching types as matching, when comparing
them between redraws to preserve active button state.

We could have avoided a bunch of issues in the past with this. They are
becoming quite common since we use more spacers and invisible elements
to enable certain behavior. Especially with nodes this caused some issues
recently.

Further code in `ui_but_update_old_active_from_new()` assumed matching
button types resulting in undefined behavior.

Fixes heap-buffer-overflow ASAN crash since 8ec9c62d3e.

Steps to reproduce were:
- Open [emitter-closures.blend](/attachments/e7689016-064c-4390-9f02-c2665b2a6a6b)
- Ctrl+Shift+Click on the header of the "Evaluate Closure" node

Pull Request: https://projects.blender.org/blender/blender/pulls/136943
This commit is contained in:
Julian Eisel
2025-04-10 20:42:10 +02:00
committed by Julian Eisel
parent b92fdff697
commit 071a6d4221

View File

@@ -774,6 +774,10 @@ bool ui_but_rna_equals_ex(const uiBut *but,
/* NOTE: if `but->poin` is allocated memory for every `uiDefBut*`, things fail. */
static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
{
if (but->type != oldbut->type) {
return false;
}
if (but->identity_cmp_func) {
/* If the buttons have their own identity comparator callbacks (and they match), use this to
* determine equality. */
@@ -829,7 +833,7 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
return false;
}
if ((but->type == UI_BTYPE_VIEW_ITEM) && (oldbut->type == UI_BTYPE_VIEW_ITEM)) {
if (but->type == UI_BTYPE_VIEW_ITEM) {
uiButViewItem *but_item = (uiButViewItem *)but;
uiButViewItem *oldbut_item = (uiButViewItem *)oldbut;
if (!but_item->view_item || !oldbut_item->view_item ||