Repository navigation
Preserve quotes and decode string literal escapes - #272
zakariyaghazzol wants to merge 4 commits into
Conversation
|
|
||
| String literals have type [String](#internal-types). | ||
|
|
||
| Single-quoted and double-quoted string literals support Python-style backslash |
There was a problem hiding this comment.
let's leave the spec unmodified for now
| from fpy.error import SyntaxErrorDuringTransform | ||
|
|
||
| try: | ||
| value = literal_eval(s) |
There was a problem hiding this comment.
Literal eval seems like a good way to do this, but the docs say:
"""
A relatively small input can lead to memory exhaustion or to C stack exhaustion, crashing the process. There is also the possibility for excessive CPU consumption denial of service on some inputs. Calling it on untrusted data is thus not recommended.
"""
Is there a way we can mitigate this? I'd recommend developing a PoC to show that this can cause denial of service in the current form, then developing a fix, then showing it no longer can DoS
|
I’ll remove the spec changes. I’m proposing to decode string escapes directly instead of using literal_eval, then test the old and new code with the same inputs and resource limits to check the specific failure and make sure existing string behavior stays the same. |
|
What I don't want is for small inputs to be able to cause DoS. I think it's more okay for a large input to do this. Maybe track it in another issue. Keep the description small, clear and precise. |
|
I compared literal_eval with a unicode_escape-based decoder on Python 3.10–3.13 by using small malformed and escape-heavy inputs under memory and time limits. I couldn’t reproduce a small-input DoS in either approach. The nesting/expression cases I checked were rejected before string decoding or remained quoted text. The other approach I tested was to decode the string escapes directly with unicode_escape. With literal_eval, Python first parses the quoted string into a syntax tree and then returns its value. The decoder would skip that extra parsing step and turn escapes like \n into their actual characters directly. But it wasn’t a simple replacement. I still needed code around it to preserve literal Unicode characters and handle newlines the same way. So it added more code to maintain, and these tests didn’t show that it solved a small-input DoS that was present with literal_eval. I did find that a raw NUL byte produces an internal-error diagnostic on Python 3.10. A small ValueError handler fixes that in the local prototype I have, and the focused string-parsing tests passed on each version. Based on these results, I plan to keep literal_eval with that handler and a regression test instead of introducing a custom decoder since it would introduce more unneeded complexity, in my opinion. |
Fixes #201.
Use
literal_evalto preserve quotes and decode escapes once. Report malformed escapes, non-UTF-8 surrogate values and raw NUL bytes as source-located errors, including Python 3.10ValueErrors. LeaveSPEC.mdunchanged.Tests check parser diagnostics and exact event text/command bytes on both sequencers. Local results: 67 focused tests passed; full suite on Python 3.12: 1,766 passed, one upstream skip, one existing XPASS. Focused parser checks also passed on Python 3.10–3.13.
Small-input probes under resource limits did not reproduce DoS in either implementation. This PR does not claim a DoS fix.