Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ Note: We're only listing outstanding class updates.
* Update Unicode to Version 17.0.0 and Emoji Version 17.0.
[[Feature #19908]][[Feature #20724]][[Feature #21275]] (also applies to Regexp)

* `String#strip`, `strip!`, `lstrip`, `lstrip!`, `rstrip`, and `rstrip!`
are extended to accept `*selectors` arguments. [[Feature #21552]]

* Thread

* Introduce support for `Thread#raise(cause:)` argument similar to
Expand Down Expand Up @@ -252,7 +255,7 @@ The following default gems are updated.
* io-nonblock 0.3.2
* io-wait 0.4.0.dev
* ipaddr 1.2.8
* json 2.17.1
* json 2.18.0
* net-http 0.8.0
* openssl 4.0.0.pre
* optparse 0.8.1
Expand Down
2 changes: 1 addition & 1 deletion ext/json/lib/json/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module JSON
VERSION = '2.17.1'
VERSION = '2.18.0'
end
36 changes: 22 additions & 14 deletions ext/json/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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"));
Expand Down
6 changes: 6 additions & 0 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -5235,6 +5235,12 @@ block_call : command do_block
$$ = new_command_qcall(p, $2, $1, $3, $4, $5, &@3, &@$);
/*% ripper: method_add_block!(command_call!($:1, $:2, $:3, $:4), $:5) %*/
}
| block_call call_op2 paren_args
{
$$ = new_qcall(p, $2, $1, idCall, $3, &@2, &@$);
nd_set_line($$, @2.end_pos.lineno);
/*% ripper: method_add_arg!(call!($:1, $:2, ID2VAL(idCall)), $:3) %*/
}
;

method_call : fcall paren_args
Expand Down
107 changes: 95 additions & 12 deletions parser_bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#include <stdint.h> /* for uintptr_t */
#include "internal/compilers.h" /* for MSC_VERSION_SINCE */

#if defined(_MSC_VER)
#ifdef _MSC_VER
# include <stdlib.h> /* for _byteswap_uint64 */
#endif

Expand All @@ -57,9 +57,6 @@
# pragma intrinsic(_rotl64)
# pragma intrinsic(_rotr64)
# endif
#endif

#if defined(_MSC_VER)
# pragma intrinsic(_BitScanForward)
# pragma intrinsic(_BitScanReverse)
# ifdef _WIN64
Expand Down Expand Up @@ -90,6 +87,7 @@

#define UNSIGNED_INTEGER_MAX(T) ((T)~(T)0)

#ifndef MUL_OVERFLOW_SIGNED_INTEGER_P
#if __has_builtin(__builtin_mul_overflow_p)
# define MUL_OVERFLOW_P(a, b) \
__builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
Expand Down Expand Up @@ -118,15 +116,100 @@
MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
#endif

#ifdef MUL_OVERFLOW_P
#if defined(MUL_OVERFLOW_P) && defined(USE___BUILTIN_MUL_OVERFLOW_LONG_LONG)
# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
#else
# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
#endif

#ifdef MUL_OVERFLOW_P
# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_P(a, b)
#else
# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
#endif
#endif

#ifndef ADD_OVERFLOW_SIGNED_INTEGER_P
#if __has_builtin(__builtin_add_overflow_p)
# define ADD_OVERFLOW_P(a, b) \
__builtin_add_overflow_p((a), (b), (__typeof__(a * b))0)
#elif __has_builtin(__builtin_add_overflow)
# define ADD_OVERFLOW_P(a, b) \
__extension__ ({ __typeof__(a) c; __builtin_add_overflow((a), (b), &c); })
#endif

#define ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
(a) > 0 ? (b) > (max) - (a) : (b) < (min) - (a))

#if __has_builtin(__builtin_add_overflow_p)
/* __builtin_add_overflow_p can take bitfield */
/* and GCC permits bitfields for integers other than int */
# define ADD_OVERFLOW_FIXNUM_P(a, b) \
__extension__ ({ \
struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
__builtin_add_overflow_p((a), (b), c.fixnum); \
})
#else
# define ADD_OVERFLOW_FIXNUM_P(a, b) \
ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
#endif

#if defined(ADD_OVERFLOW_P) && defined(USE___BUILTIN_ADD_OVERFLOW_LONG_LONG)
# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
#else
# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
#endif

#ifdef ADD_OVERFLOW_P
# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_P(a, b)
#else
# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
#endif
#endif

#ifndef SUB_OVERFLOW_SIGNED_INTEGER_P
#if __has_builtin(__builtin_sub_overflow_p)
# define SUB_OVERFLOW_P(a, b) \
__builtin_sub_overflow_p((a), (b), (__typeof__(a * b))0)
#elif __has_builtin(__builtin_sub_overflow)
# define SUB_OVERFLOW_P(a, b) \
__extension__ ({ __typeof__(a) c; __builtin_sub_overflow((a), (b), &c); })
#endif

#define SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
(b) > 0 ? (a) < (min) + (b) : (a) > (max) + (b))

#if __has_builtin(__builtin_sub_overflow_p)
/* __builtin_sub_overflow_p can take bitfield */
/* and GCC permits bitfields for integers other than int */
# define SUB_OVERFLOW_FIXNUM_P(a, b) \
__extension__ ({ \
struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
__builtin_sub_overflow_p((a), (b), c.fixnum); \
})
#else
# define SUB_OVERFLOW_FIXNUM_P(a, b) \
SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
#endif

#if defined(SUB_OVERFLOW_P) && defined(USE___BUILTIN_SUB_OVERFLOW_LONG_LONG)
# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
#else
# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
#endif

#ifdef SUB_OVERFLOW_P
# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_P(a, b)
#else
# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
#endif
#endif

#ifdef HAVE_UINT128_T
# define bit_length(x) \
Expand Down Expand Up @@ -394,9 +477,9 @@ rb_popcount32(uint32_t x)
#else
x = (x & 0x55555555) + (x >> 1 & 0x55555555);
x = (x & 0x33333333) + (x >> 2 & 0x33333333);
x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f);
x = (x & 0x001f001f) + (x >> 8 & 0x001f001f);
x = (x & 0x0000003f) + (x >>16 & 0x0000003f);
x = (x & 0x07070707) + (x >> 4 & 0x07070707);
x = (x & 0x000f000f) + (x >> 8 & 0x000f000f);
x = (x & 0x0000001f) + (x >>16 & 0x0000001f);
return (unsigned int)x;

#endif
Expand Down Expand Up @@ -424,9 +507,9 @@ rb_popcount64(uint64_t x)
x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707);
x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f);
x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f);
x = (x & 0x000000000000007f) + (x >>32 & 0x000000000000007f);
x = (x & 0x000f000f000f000f) + (x >> 8 & 0x000f000f000f000f);
x = (x & 0x0000001f0000001f) + (x >>16 & 0x0000001f0000001f);
x = (x & 0x000000000000003f) + (x >>32 & 0x000000000000003f);
return (unsigned int)x;

#endif
Expand Down
Loading