Skip to content

Commit 9035400

Browse files
committed
Integrate with Ruby 4.1 ruby_sized_xfree
Ensure that buffer sizes have been properly tracked when running in debug mode, and appease the GC slightly when running in release mode. Ref: https://bugs.ruby-lang.org/issues/21861
1 parent f7fe86e commit 9035400

6 files changed

Lines changed: 27 additions & 5 deletions

File tree

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
### Unreleased
44

5+
* Integrate with Ruby 4.1 `ruby_sized_xfree`.
6+
57
### 2026-06-03 (2.19.8)
68

79
* Fix 1-byte buffer overread on EOS errors.

ext/json/ext/fbuffer/fbuffer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
6464
static void fbuffer_free(FBuffer *fb)
6565
{
6666
if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
67-
ruby_xfree(fb->ptr);
67+
JSON_SIZED_FREE_N(fb->ptr, fb->capa);
6868
}
6969
}
7070

@@ -88,7 +88,7 @@ static void fbuffer_realloc(FBuffer *fb, size_t required)
8888
fb->type = FBUFFER_HEAP_ALLOCATED;
8989
MEMCPY(fb->ptr, old_buffer, char, fb->len);
9090
} else {
91-
REALLOC_N(fb->ptr, char, required);
91+
JSON_SIZED_REALLOC_N(fb->ptr, char, required, fb->capa);
9292
}
9393
fb->capa = required;
9494
}

ext/json/ext/generator/extconf.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
else
77
append_cflags("-std=c99")
88
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
9+
have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
910

1011
$defs << "-DJSON_GENERATOR"
1112
$defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"

ext/json/ext/json.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@ typedef unsigned char _Bool;
4949
#endif
5050
#endif
5151

52+
#ifndef HAVE_RUBY_XFREE_SIZED
53+
static inline void ruby_xfree_sized(void *ptr, size_t oldsize)
54+
{
55+
ruby_xfree(ptr);
56+
}
57+
58+
static inline void *ruby_xrealloc2_sized(void *ptr, size_t new_elems, size_t elem_size, size_t old_elems)
59+
{
60+
return ruby_xrealloc2(ptr, new_elems, elem_size);
61+
}
62+
#endif
63+
64+
# define JSON_SIZED_REALLOC_N(v, T, m, n) \
65+
((v) = (T *)ruby_xrealloc2_sized((void *)(v), (m), sizeof(T), (n)))
66+
67+
# define JSON_SIZED_FREE(v) ruby_xfree_sized((void *)(v), sizeof(*(v)))
68+
# define JSON_SIZED_FREE_N(v, n) ruby_xfree_sized((void *)(v), sizeof(*(v)) * (n))
69+
5270
#ifndef HAVE_RB_EXT_RACTOR_SAFE
5371
# undef RUBY_TYPED_FROZEN_SHAREABLE
5472
# define RUBY_TYPED_FROZEN_SHAREABLE 0

ext/json/ext/parser/extconf.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
have_func("rb_str_to_interned_str", "ruby.h") # RUBY_VERSION >= 3.0
77
have_func("rb_hash_new_capa", "ruby.h") # RUBY_VERSION >= 3.2
88
have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby
9+
have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
910

1011
if RUBY_ENGINE == "ruby"
1112
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3

ext/json/ext/parser/parser.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalu
211211
if (stack->type == RVALUE_STACK_STACK_ALLOCATED) {
212212
stack = rvalue_stack_spill(stack, handle, stack_ref);
213213
} else {
214-
REALLOC_N(stack->ptr, VALUE, required);
214+
JSON_SIZED_REALLOC_N(stack->ptr, VALUE, required, stack->capa);
215215
stack->capa = required;
216216
}
217217
return stack;
@@ -250,7 +250,7 @@ static void rvalue_stack_mark(void *ptr)
250250

251251
static void rvalue_stack_free_buffer(rvalue_stack *stack)
252252
{
253-
ruby_xfree(stack->ptr);
253+
JSON_SIZED_FREE_N(stack->ptr, stack->capa);
254254
stack->ptr = NULL;
255255
}
256256

@@ -260,7 +260,7 @@ static void rvalue_stack_free(void *ptr)
260260
if (stack) {
261261
rvalue_stack_free_buffer(stack);
262262
#ifndef HAVE_RUBY_TYPED_EMBEDDABLE
263-
ruby_xfree(stack);
263+
JSON_SIZED_FREE(stack);
264264
#endif
265265
}
266266
}

0 commit comments

Comments
 (0)