diff options
| author | Jean Boussier <jean.boussier@gmail.com> | 2025-12-11 11:09:05 +0100 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2025-12-11 10:53:15 +0000 |
| commit | 6ad4e6a298e7b5d0f925aacecc5d375968ebde15 (patch) | |
| tree | 4c22230319f88fab95b6f9ab0862c7ddf5bc535e /ext/json/parser/parser.c | |
| parent | 281a000d6669d3fbb1c0a2f940cbb9c7c01732e6 (diff) | |
[ruby/json] Add `allow_control_characters` parsing option
While it's not allowed by the spec, some parsers like Oj do
accept it, and it can be blocking a transition.
Having this feature can help people migrate.
https://github.com/ruby/json/commit/3459499cb3
Diffstat (limited to 'ext/json/parser/parser.c')
| -rw-r--r-- | ext/json/parser/parser.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 45de8d1ff6..8f9729ef28 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -7,7 +7,7 @@ static VALUE CNaN, CInfinity, CMinusInfinity; static ID i_new, i_try_convert, i_uminus, i_encode; -static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_symbolize_names, sym_freeze, +static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_allow_control_characters, sym_symbolize_names, sym_freeze, sym_decimal_class, sym_on_load, sym_allow_duplicate_key; static int binary_encindex; @@ -335,6 +335,7 @@ typedef struct JSON_ParserStruct { int max_nesting; bool allow_nan; bool allow_trailing_comma; + bool allow_control_characters; bool symbolize_names; bool freeze; } JSON_ParserConfig; @@ -752,12 +753,15 @@ NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_Parser break; default: if ((unsigned char)*pe < 0x20) { - if (*pe == '\n') { - raise_parse_error_at("Invalid unescaped newline character (\\n) in string: %s", state, pe - 1); + if (!config->allow_control_characters) { + if (*pe == '\n') { + raise_parse_error_at("Invalid unescaped newline character (\\n) in string: %s", state, pe - 1); + } + raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1); } - raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1); + } else { + raise_parse_error_at("invalid escape character in string: %s", state, pe - 1); } - raise_parse_error_at("invalid escape character in string: %s", state, pe - 1); break; } } @@ -1009,7 +1013,9 @@ static VALUE json_parse_escaped_string(JSON_ParserState *state, JSON_ParserConfi break; } default: - raise_parse_error("invalid ASCII control character in string: %s", state); + if (!config->allow_control_characters) { + raise_parse_error("invalid ASCII control character in string: %s", state); + } break; } @@ -1430,14 +1436,15 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data) { JSON_ParserConfig *config = (JSON_ParserConfig *)data; - if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; } - else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); } - else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); } - else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); } - else if (key == sym_freeze) { config->freeze = RTEST(val); } - else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; } - else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; } - else if (key == sym_decimal_class) { + if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; } + else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); } + else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); } + else if (key == sym_allow_control_characters) { config->allow_control_characters = RTEST(val); } + else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); } + else if (key == sym_freeze) { config->freeze = RTEST(val); } + else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; } + else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; } + else if (key == sym_decimal_class) { if (RTEST(val)) { if (rb_respond_to(val, i_try_convert)) { config->decimal_class = val; @@ -1650,6 +1657,7 @@ void Init_parser(void) sym_max_nesting = ID2SYM(rb_intern("max_nesting")); sym_allow_nan = ID2SYM(rb_intern("allow_nan")); sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma")); + sym_allow_control_characters = ID2SYM(rb_intern("allow_control_characters")); sym_symbolize_names = ID2SYM(rb_intern("symbolize_names")); sym_freeze = ID2SYM(rb_intern("freeze")); sym_on_load = ID2SYM(rb_intern("on_load")); |
