godotengine / godotengine/godot
`String.json_escape` does not escape ASCII control codes
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
Reproducible in 4.4.1-stable and master as of writing a3b42d85d27668f8992c0779ed3cc82d13db3dd9
### System information
macOS Sequoia 15.6
### Issue description
`String.json_escape` does not work for ASCII control codes.
The [JSON specification](https://www.ietf.org/rfc/rfc4627.txt) explicitly allows hexadecimal `\u` notation:
> Any character may be escaped. If the character is in the Basic
Multilingual Plane (U+0000 through U+FFFF), then it may be
represented as a six-character sequence: a reverse solidus, followed
by the lowercase letter u, followed by four hexadecimal digits that
encode the character's code point. The hexadecimal letters A though
F can be upper or lowercase. So, for example, a string containing
only a single reverse solidus character may be represented as
"\u005C".
Test code:
```gdscript
func _ready() -> void:
print("\u0001\u0002\u0003\u0004".json_escape())
print("\u0021\u0022\u0023\u0024".json_escape())
```
Expected output:
```
\u0001\u0002\u0003\u0004
!\"#$
```
Actual output:
```
!\"#$
```
Screenshot in case browsers don't want to render those:
The JSON spec explicitly forbids ASCII control codes from being in the string unescaped:
> All Unicode characters may be placed within the
quotation marks except for the characters that must be escaped:
quotation mark, reverse solidus, and the control characters (U+0000
through U+001F).
EDIT: Oh, also, we should escape the extended Unicode control codes (`0x7F` to `0x9F`).
### Steps to reproduce
Paste the above code in a Godot project and run it.
### Minimal reproduction project (MRP)
It's 2 print statements, I won't bother making a MRP ZIP for this.
Contributor guide
Research direction
Start at the String.json_escape entry point and reproduce the issue with the provided GDScript examples. Compare the output with the JSON requirements for U+0000–U+001F and the additionally requested U+007F–U+009F range; done means those control codes are escaped while the existing output remains correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100