Skip to content
This repository has been archived by the owner on Dec 1, 2021. It is now read-only.

if an error somehow wraps itself, Error() recurses forever #131

Open
lunixbochs opened this issue Aug 31, 2017 · 2 comments
Open

if an error somehow wraps itself, Error() recurses forever #131

lunixbochs opened this issue Aug 31, 2017 · 2 comments

Comments

@lunixbochs
Copy link

I know it's totally my bad to cause this in the first place, but I've somehow made err.Error() recurse forever, which means the err itself is the cause. I haven't tracked it down yet, but detecting if the Error() chain loops might be nice, as I had to use delve and print 200k lines of stacktrace to figure out what was wrong.

https://github.com/pkg/errors/blob/master/errors.go#L228

@davecheney
Copy link
Member

davecheney commented Aug 31, 2017 via email

@lunixbochs
Copy link
Author

lunixbochs commented Sep 1, 2017

Okay, so this was a different problem than I thought- so not a recursive error- (and totally my fault): a file format parser bug resulted in the next input "frame" being parsed as a recursion of the previous frame. When the very last frame throws io.EOF, it bubbles all the way out (200k stack frames, 200k times errors.Wrap()).

Now withMessage.Error() is quadratic time due to the simple string concat, so deeply nested errors are actually pretty slow as per this gist (which needs to be run locally, not on play.golang.org): https://gist.github.com/lunixbochs/00262cfc53c5096b57274768209f6aa6

I get this output for 20k iterations:

quadratic 511.538ms 100005
linear 2.830926ms 100008

It was taking tens of seconds to print the error message, which is why my stack trace was just miles of withMessage.Error().

Now, I don't think this is real-world case enough to actually fix like this (as a dumb list join is slower for real-world error nesting, like ~20), but if someone in the future ever ends up with this many nested errors.withMessage they will be just as confused as me.

It's also a contrived DoS case.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants