DelegateDecompiler icon indicating copy to clipboard operation
DelegateDecompiler copied to clipboard

Self referencing computed property will cause an infinite loop and stackoverflow

Open mwillebrands opened this issue 11 years ago • 12 comments

When having a self referencing property with the computed attribute, delegatedecompiler will create an infinite loop and causes a stackoverflow.

See the testcase for an example project https://www.dropbox.com/s/40070ysin7h01j3/Self%20reference%20property%20overflowexception.zip?dl=0

mwillebrands avatar Apr 01 '15 07:04 mwillebrands

If you change the property from if(Base == null)

to if ( Base == null || Base == default(TestClass)) It works. Maybe helps fixing the stuff.

mwillebrands avatar Apr 01 '15 10:04 mwillebrands

Hi @mwillebrands, I've looked into the problem and it seems that the "fix" works when you cache Base to an variable.

hazzik avatar Apr 01 '15 19:04 hazzik

Hi Alexander,

Thanks for your response. Could you maybe explain it a bit more, i don't really understand. I've tried looking through your source, but couldn't really find a way to fix it.

Thanks Maarten

mwillebrands avatar Apr 01 '15 19:04 mwillebrands

@mwillebrands if you'll take a look to the difference in IL between "Debug" and "Release" versions you can get some ideas; however I'm not sure how to fix this yet.

hazzik avatar Apr 01 '15 19:04 hazzik

Yeah i did, all i could think of is limit the amount of hoe many levels deep the decompiling should go. That works, however it is an hidious way to fix it ;)

mwillebrands avatar Apr 01 '15 19:04 mwillebrands

But, I'm not sure how the decompiled expression tree should look like.

hazzik avatar Apr 01 '15 20:04 hazzik

Well, i'm not really sure what causes the problem to arise in release. It's almost doing the same thing. Do you know what line in the IL causes it?

[DEBUG] http://hastebin.com/raqecebewi.py

[RELEASE] http://hastebin.com/iredufowur.il

They both should call get_Base and get_Test

mwillebrands avatar Apr 02 '15 07:04 mwillebrands

The control flows for both seem to involve the three function calls. However, release only ever ldarg.0's, whereas debug does stloc.0 and ldloc.0 before returning. Perhaps modifying whatever generates that IL into having the same ldarg.0 -> function -> stloc.0 -> ldloc.0 -> ret flow (instead of ldarg.0 -> function -> ret) would work, given that caching Base to a variable beforehand makes it work. The immediate downside that I see there is that it might be slow, but you could test for that.

krageon avatar Apr 02 '15 08:04 krageon

Yeah, that would work, however, i can't seem to get the same IL whatever i do. And this is pretty faulty, if a new version of the compiler changes the IL, you'll get strange errors and you don't know why...

I've changed it for now so it won't use Computed properties which reference itself, it's ugly, but it works. (Duplicated the logic in all the queries)

Could we build in that DelegateDecompiler will not generate a stackoverflow, but throws an exception if it goes like 1000 levels deep or something? I've put it in my own version, but maybe it's convenient for other people as well.

mwillebrands avatar Apr 02 '15 08:04 mwillebrands

You might try implementing your workaround (caching before the call) and keeping the original workflow around, then making an test that tests both (and expects a problem on the original flow). Then when you upgrade your environment, you will know if it's different.

krageon avatar Apr 02 '15 09:04 krageon

True, however i can't get the IL to be the same as the debug version. I think focusing on getting the IL the same isn't the way we should go.

mwillebrands avatar Apr 02 '15 15:04 mwillebrands

I think focusing on getting the IL the same isn't the way we should go.

Yes.

hazzik avatar Apr 06 '15 20:04 hazzik