Skip to content

Conversation

@AkiSakurai
Copy link

struct Rec : Rec {
};

Prevent infinite recursion in appendInheritances by erasing processed
inheritance entries during traversal, and safely iterate over
m_inheritances in appendInheritances to avoid
modification-during-iteration issues.

… structs

``` rust
struct Rec : Rec {
};
```

Prevent infinite recursion in appendInheritances by erasing processed
inheritance entries during traversal, and safely iterate over
m_inheritances in appendInheritances to avoid
modification-during-iteration issues.
@paxcut
Copy link
Collaborator

paxcut commented Dec 8, 2025

Thanks for looking into this and even writing a fix for it. As happy as it makes me to see other involved in these project I feel that this fix should be a lot simpler for what it really does. All we care about is making sure that there is no crash. We don't really care about which entries may be causing the infinite recursion and in most cases there is no single element or set of them that can be used to fix things by removing it. It is not clear what the effect of removing elements on one inheritance chain may have on other chains that share some of the inheritance links but are not part of the infinite recursion. On top of that you need to watch for the effects of removing items from the iterators and it just gets too complicated when thinking about it in those terms.

A more reasonable approach is to rely on the fact that if we have N distinct inheritance nodes any directed graph made from them that contains no loops can have at most N*(N-1)/2 possible connections between them. Inheritance nodes also include the Base structs that are not derived from other structs so it isn't just the size of m_inheritances.

A fast way to calculate it would be to create a set of strings and dump all the names in the m_inheritances map in there, both the keys and the values. Then use the size of the resulting set to obtain N*(N-1), initialize an integer to 0 in the function calling the recursion and pass it as a reference to the recursion functions. The function simply add one before calling each recursion and if the number exceeds the max you know there's a loop somewhere so you can can just return.

About the values of the m_inheritance map I think that using a vector of strings is a mistake because it would make no sense for the same struct to appear more than once. That train of thought made me realize that the current implementation of inheritance in ImHex is not dealing with the Diamond problem in any form and that it is possible to create derived classes with multiple copies of variables where only the last one created can be accessed, but that not really part of this PR so i'll stop for now.

Let me know what you think of this and how you want to proceed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants