revset: bound recursion during resolution - #10216
mirkomartn wants to merge 2 commits into
Conversation
|
Can you provide sufficient motivation in the commit message and move the fixes line into it to adhere to our commit guidellines. Thanks. |
|
It's too late to reject deep expressions at the symbol resolution stage. We probably need a parsing-stage depth limit. Some related discussion in pest-parser/pest#1129 |
Add a simple function for checking if the remaining stack size is still above required minimum. This allows for a crude mechanism guarding against stack overflows. Instead of growing the stack on the heap (as is the usual use-case of the stacker), simply detect that the limit was reached and return an error, allowing the caller to deal with it however desired.
Before recursing deeper, always check that there's enough space left on the stack. If we leave this unbounded, we allow for a very simple, yet powerful DoS vector.
8739bce to
36ebe47
Compare
Added a stacker-based check, so that we can check preemptively how much space is still left on the stack, before recursing deeper. I left it at the same place (was just the least work to do so), but I think it should be very straightforward to add the same check at other places where there's currently unbounded recursion, if there's an agreement to go about it this way. I'm also unclear on whether we should have a global bound on minimal space left on stack (what I think I'd prefer), or whether the limit could be specified at call-site. I currently set it to 20kb and I could confirm that the reproducer in the original issue no longer crashes (15kb on the other hand was too low and jj crashed). |
|
I applied this locally (macOS arm64) and ran the reproducer from #10071 plus some variants. It still overflows in every case, in both debug and release builds. Two separate causes:
Two smaller things: Given all that, I think a deterministic nesting-depth limit in the three parsers (plus a cap in alias expansion) would be simpler and would cover every downstream pass, along the lines suggested in the issue thread. |
Thanks for taking your time and checking!
Right, this was just a "works on my machine" example and I think we can and should have a conservatively high value for RED_ZONE (user can potentially always increase the stack size allocated by the OS).
Yes, that much was expected per the previous comment from @yuja, but as said, I first wanted to get an agreement on the mechanism and then apply it broadly.
Not sure I agree with the
Agree, but only that I would use a stacker mechanism instead of nesting-depth (which was what I originally went with). I think it's just more composable/generic and could potentially be used elsewhere. But again, don't feel strongly about it to argue for it. |
Fixes #10071.
An alternative would be to use stacker.
We might also consider making the limit configurable.
Checklist
If applicable:
CHANGELOG.mdREADME.md,docs/,demos/)cli/src/config-schema.json)how it works, how it's organized), including any code drafted by an LLM.
an eye towards deleting anything that is irrelevant, clarifying anything
that is confusing, and adding details that are relevant. This includes,
for example, commit descriptions, PR descriptions, and code comments.