Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guard against infinite expectation loops, especially in global handlers #3

Open
ngsilverman opened this issue Nov 20, 2020 · 4 comments
Labels
enhancement New feature or request

Comments

@ngsilverman
Copy link
Contributor

Using expectations instead of handlers, especially the global one, could cause infinite loops when they fail.

expect.onGlobalFail = object : GlobalExpectationHandler() {
    override fun handleFail(exception: ExpectationException) {
        expect.fail("this will trigger an infinite loop as soon as an expectation fails")
    }
}

This is easy to avoid when the global handler logic is simple, which I expect to be the majority of cases, but it could be done inadvertently for more complex handlers who make various function calls, for example to disable parts of the application.

Since the purpose of the library is in part to be able to recover critical failures, it would be unfortunate to cause one. Ideally we would detect loops that are likely infinite and end them before a stack overflow. The approach could perhaps consist of detecting if multiple calls to handleFail are occurring without any of the calls returning. By inspecting the ExpectationException one could make an educated guess as to whether the same expectation is failing in a loop.

@ngsilverman ngsilverman added the enhancement New feature or request label Nov 20, 2020
@indragiek
Copy link
Member

Detecting the loop based on the stack trace sounds like a good idea 👍 It seems like you could decompose the stack trace into its individual frames, then do a simple check for cycles of frames that include the global expectation handler frame.

@ngsilverman
Copy link
Contributor Author

Yeah, checking the stack trace itself is a good idea but only works if the calls are made from the same thread. Granted, I think that's pretty likely, but it's not a perfect solution. 😓

@odeke-em
Copy link

Howdy my good ole folks @ngsilverman @indragiek! Just chiming in, with a question and perhaps a remedy. Can we perhaps check for program counters and/or function pointers to detect loops? If Kotlin doesn’t provide these, then no biggie, please discard, but if it does, usually the runtime arranges for them to be unique uintptr/uint64 values that could be checked for, (obviously after unfurling inclined calls)

@ngsilverman
Copy link
Contributor Author

Hey @odeke-em! Thanks for chiming in. The JVM Tool Interface does appear to provide access to executable locations of methods, but that's not an API meant to be used by a library like this one. For practical purposes this doesn't seem possible for Kotlin (or Java). Function pointers are not available at all as far as I can tell. 🤷‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants