json 2.10.1 → 2.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +6 -0
- data/ext/json/ext/parser/parser.c +43 -35
- data/lib/json/common.rb +6 -12
- data/lib/json/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b909ed90787afa31835c9926529808ca3c6b161755e1f6126b7fe203231fa0c2
|
4
|
+
data.tar.gz: efd6a873e98f9e4b2b8c078210f141dfde5f3773884bd5851f228c184ff94ff7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bff39363d5d7fa2f209d5bf97a5728738058bc83600b732d95487e263a5a3901b1e18d5c42d7d2be019ac55ef069a50cedc1d9a8d22b11e6061f2eef747dc94d
|
7
|
+
data.tar.gz: 693e480f8f2489e26c43eef56ad8977ab3f00fada03318a48b88ac55e2b82b15ffae92fd05dd47d86686fae39169b079f59a68fffc6efaf44ee3503a45060e30
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
### 2025-03-12 (2.10.2)
|
4
|
+
|
5
|
+
* Fix a potential crash in the C extension parser.
|
6
|
+
* Raise a ParserError on all incomplete unicode escape sequence. This was the behavior until `2.10.0` unadvertently changed it.
|
7
|
+
* Ensure document snippets that are included in parser errors don't include truncated multibyte characters.
|
8
|
+
|
3
9
|
### 2025-02-10 (2.10.1)
|
4
10
|
|
5
11
|
* Fix a compatibility issue with `MultiJson.dump(obj, pretty: true)`: `no implicit conversion of false into Proc (TypeError)`.
|
@@ -341,6 +341,44 @@ static void rvalue_stack_eagerly_release(VALUE handle)
|
|
341
341
|
}
|
342
342
|
}
|
343
343
|
|
344
|
+
|
345
|
+
#ifndef HAVE_STRNLEN
|
346
|
+
static size_t strnlen(const char *s, size_t maxlen)
|
347
|
+
{
|
348
|
+
char *p;
|
349
|
+
return ((p = memchr(s, '\0', maxlen)) ? p - s : maxlen);
|
350
|
+
}
|
351
|
+
#endif
|
352
|
+
|
353
|
+
#define PARSE_ERROR_FRAGMENT_LEN 32
|
354
|
+
#ifdef RBIMPL_ATTR_NORETURN
|
355
|
+
RBIMPL_ATTR_NORETURN()
|
356
|
+
#endif
|
357
|
+
static void raise_parse_error(const char *format, const char *start)
|
358
|
+
{
|
359
|
+
unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 1];
|
360
|
+
|
361
|
+
size_t len = start ? strnlen(start, PARSE_ERROR_FRAGMENT_LEN) : 0;
|
362
|
+
const char *ptr = start;
|
363
|
+
|
364
|
+
if (len == PARSE_ERROR_FRAGMENT_LEN) {
|
365
|
+
MEMCPY(buffer, start, char, PARSE_ERROR_FRAGMENT_LEN);
|
366
|
+
|
367
|
+
while (buffer[len - 1] >= 0x80 && buffer[len - 1] < 0xC0) { // Is continuation byte
|
368
|
+
len--;
|
369
|
+
}
|
370
|
+
|
371
|
+
if (buffer[len - 1] >= 0xC0) { // multibyte character start
|
372
|
+
len--;
|
373
|
+
}
|
374
|
+
|
375
|
+
buffer[len] = '\0';
|
376
|
+
ptr = (const char *)buffer;
|
377
|
+
}
|
378
|
+
|
379
|
+
rb_enc_raise(enc_utf8, rb_path2class("JSON::ParserError"), format, ptr);
|
380
|
+
}
|
381
|
+
|
344
382
|
/* unicode */
|
345
383
|
|
346
384
|
static const signed char digit_values[256] = {
|
@@ -362,21 +400,19 @@ static const signed char digit_values[256] = {
|
|
362
400
|
|
363
401
|
static uint32_t unescape_unicode(const unsigned char *p)
|
364
402
|
{
|
365
|
-
const uint32_t replacement_char = 0xFFFD;
|
366
|
-
|
367
403
|
signed char b;
|
368
404
|
uint32_t result = 0;
|
369
405
|
b = digit_values[p[0]];
|
370
|
-
if (b < 0)
|
406
|
+
if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
|
371
407
|
result = (result << 4) | (unsigned char)b;
|
372
408
|
b = digit_values[p[1]];
|
373
|
-
if (b < 0)
|
409
|
+
if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
|
374
410
|
result = (result << 4) | (unsigned char)b;
|
375
411
|
b = digit_values[p[2]];
|
376
|
-
if (b < 0)
|
412
|
+
if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
|
377
413
|
result = (result << 4) | (unsigned char)b;
|
378
414
|
b = digit_values[p[3]];
|
379
|
-
if (b < 0)
|
415
|
+
if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
|
380
416
|
result = (result << 4) | (unsigned char)b;
|
381
417
|
return result;
|
382
418
|
}
|
@@ -440,34 +476,6 @@ typedef struct JSON_ParserStateStruct {
|
|
440
476
|
|
441
477
|
static const rb_data_type_t JSON_ParserConfig_type;
|
442
478
|
|
443
|
-
#ifndef HAVE_STRNLEN
|
444
|
-
static size_t strnlen(const char *s, size_t maxlen)
|
445
|
-
{
|
446
|
-
char *p;
|
447
|
-
return ((p = memchr(s, '\0', maxlen)) ? p - s : maxlen);
|
448
|
-
}
|
449
|
-
#endif
|
450
|
-
|
451
|
-
#define PARSE_ERROR_FRAGMENT_LEN 32
|
452
|
-
#ifdef RBIMPL_ATTR_NORETURN
|
453
|
-
RBIMPL_ATTR_NORETURN()
|
454
|
-
#endif
|
455
|
-
static void raise_parse_error(const char *format, const char *start)
|
456
|
-
{
|
457
|
-
char buffer[PARSE_ERROR_FRAGMENT_LEN + 1];
|
458
|
-
|
459
|
-
size_t len = start ? strnlen(start, PARSE_ERROR_FRAGMENT_LEN) : 0;
|
460
|
-
const char *ptr = start;
|
461
|
-
|
462
|
-
if (len == PARSE_ERROR_FRAGMENT_LEN) {
|
463
|
-
MEMCPY(buffer, start, char, PARSE_ERROR_FRAGMENT_LEN);
|
464
|
-
buffer[PARSE_ERROR_FRAGMENT_LEN] = '\0';
|
465
|
-
ptr = buffer;
|
466
|
-
}
|
467
|
-
|
468
|
-
rb_enc_raise(enc_utf8, rb_path2class("JSON::ParserError"), format, ptr);
|
469
|
-
}
|
470
|
-
|
471
479
|
static const bool whitespace[256] = {
|
472
480
|
[' '] = 1,
|
473
481
|
['\t'] = 1,
|
@@ -600,7 +608,7 @@ static VALUE json_string_unescape(JSON_ParserState *state, const char *string, c
|
|
600
608
|
buffer = RSTRING_PTR(result);
|
601
609
|
bufferStart = buffer;
|
602
610
|
|
603
|
-
while ((pe = memchr(pe, '\\', stringEnd - pe))) {
|
611
|
+
while (pe < stringEnd && (pe = memchr(pe, '\\', stringEnd - pe))) {
|
604
612
|
unescape = (char *) "?";
|
605
613
|
unescape_len = 1;
|
606
614
|
if (pe > p) {
|
data/lib/json/common.rb
CHANGED
@@ -152,10 +152,13 @@ module JSON
|
|
152
152
|
end
|
153
153
|
|
154
154
|
def detailed_message(...)
|
155
|
+
# Exception#detailed_message doesn't exist until Ruby 3.2
|
156
|
+
super_message = defined?(super) ? super : message
|
157
|
+
|
155
158
|
if @invalid_object.nil?
|
156
|
-
|
159
|
+
super_message
|
157
160
|
else
|
158
|
-
"#{
|
161
|
+
"#{super_message}\nInvalid object: #{@invalid_object.inspect}"
|
159
162
|
end
|
160
163
|
end
|
161
164
|
end
|
@@ -840,7 +843,7 @@ module JSON
|
|
840
843
|
|
841
844
|
opts = JSON.dump_default_options
|
842
845
|
opts = opts.merge(:max_nesting => limit) if limit
|
843
|
-
opts =
|
846
|
+
opts = opts.merge(kwargs) if kwargs
|
844
847
|
|
845
848
|
begin
|
846
849
|
State.generate(obj, opts, anIO)
|
@@ -854,15 +857,6 @@ module JSON
|
|
854
857
|
string.encode(to, from)
|
855
858
|
end
|
856
859
|
|
857
|
-
def merge_dump_options(opts, strict: NOT_SET)
|
858
|
-
opts = opts.merge(strict: strict) if NOT_SET != strict
|
859
|
-
opts
|
860
|
-
end
|
861
|
-
|
862
|
-
class << self
|
863
|
-
private :merge_dump_options
|
864
|
-
end
|
865
|
-
|
866
860
|
# JSON::Coder holds a parser and generator configuration.
|
867
861
|
#
|
868
862
|
# module MyApp
|
data/lib/json/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.10.
|
4
|
+
version: 2.10.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-03-12 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: This is a JSON implementation as a Ruby extension in C.
|
13
13
|
email: flori@ping.de
|