schemagen emits unescaped control characters in generated C++ string literals #35

Closed
opened 2026-06-28 15:41:50 +00:00 by weaselbot · 0 comments
Member

When a JSON Schema contains object property keys or string enum values that include control characters (e.g. an escaped newline written as the actual newline character after json.load), the generated header contains C++ string literals with raw newlines. This breaks compilation because the C++ tokenizer sees the string as terminated at the newline.

Relevant code

File: contrib/schemagen/weaseljson_schemagen.py

  • Line 621 (_struct_decls): field comments embed the raw JSON key.
  • Line 750 (_matchkey): object-key comparison literals only escape \ and ".
  • Lines 833-834 (_enum_name_arrays): enum-name array literals only escape \ and ".
esc = fld.key.replace("\\", "\\\\").replace('"', '\\"')
...
'"' + v.replace("\\", "\\\\").replace('"', '\\"') + '"'

Neither path escapes newlines, tabs, carriage returns, or other control characters, so they are emitted verbatim into the generated source.

Reproduction

Schema with a newline in a property key:

{"type": "object", "properties": {"a\nb": {"type": "string"}}}

Schema with a newline in an enum value:

{"type": "object", "properties": {"x": {"enum": ["a\nb"]}}}

Run:

python3 contrib/schemagen/weaseljson_schemagen.py schema.json -o gen.h --namespace ns
c++ -std=c++20 -Iinclude -c gen.h

Result (key case shown; enum case is analogous):

gen.h:21:2: error: missing terminating " character
   21 | b"
      |  ^
gen.h:403:18: error: missing terminating " character
  403 |       if (key == "a
      |                  ^

Expected behavior

The generator should produce valid C++ string literals for any JSON-string-legal character, including control characters. At minimum it should escape \n, \r, \t, and other bytes below 0x20 using \u00xx or octal/hex escapes, while still escaping \\ and \" as it already does.

Actual behavior

The generated header contains raw control characters inside string literals and fails to compile.

Impact

Any schema that uses keys or enum values with control characters (common when schemas are generated from real data or when enum values contain formatted text) will produce an uncompilable parser. This is a silent generation failure rather than a clear schema-rejection error.

When a JSON Schema contains object property keys or string enum values that include control characters (e.g. an escaped newline written as the actual newline character after `json.load`), the generated header contains C++ string literals with raw newlines. This breaks compilation because the C++ tokenizer sees the string as terminated at the newline. **Relevant code** File: `contrib/schemagen/weaseljson_schemagen.py` - Line 621 (`_struct_decls`): field comments embed the raw JSON key. - Line 750 (`_matchkey`): object-key comparison literals only escape `\` and `"`. - Lines 833-834 (`_enum_name_arrays`): enum-name array literals only escape `\` and `"`. ```python esc = fld.key.replace("\\", "\\\\").replace('"', '\\"') ... '"' + v.replace("\\", "\\\\").replace('"', '\\"') + '"' ``` Neither path escapes newlines, tabs, carriage returns, or other control characters, so they are emitted verbatim into the generated source. **Reproduction** Schema with a newline in a property key: ```json {"type": "object", "properties": {"a\nb": {"type": "string"}}} ``` Schema with a newline in an enum value: ```json {"type": "object", "properties": {"x": {"enum": ["a\nb"]}}} ``` Run: ```sh python3 contrib/schemagen/weaseljson_schemagen.py schema.json -o gen.h --namespace ns c++ -std=c++20 -Iinclude -c gen.h ``` Result (key case shown; enum case is analogous): ``` gen.h:21:2: error: missing terminating " character 21 | b" | ^ gen.h:403:18: error: missing terminating " character 403 | if (key == "a | ^ ``` **Expected behavior** The generator should produce valid C++ string literals for any JSON-string-legal character, including control characters. At minimum it should escape `\n`, `\r`, `\t`, and other bytes below `0x20` using `\u00xx` or octal/hex escapes, while still escaping `\\` and `\"` as it already does. **Actual behavior** The generated header contains raw control characters inside string literals and fails to compile. **Impact** Any schema that uses keys or enum values with control characters (common when schemas are generated from real data or when enum values contain formatted text) will produce an uncompilable parser. This is a silent generation failure rather than a clear schema-rejection error.
weaselbot was assigned by andrew 2026-06-30 16:18:44 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: weaselab/weaseljson#35