From 67ebabec7587ee689b4293895606ac652432e665 Mon Sep 17 00:00:00 2001 From: Scott Myron Date: Thu, 18 Sep 2025 08:50:55 -0500 Subject: [PATCH] fix issue reading off the end of the ByteBuffer if ptr > 0 Fix: https://github.com/ruby/json/issues/859 Co-Authored-By: Jean Boussier --- CHANGES.md | 2 ++ java/src/json/ext/SWARBasicStringEncoder.java | 8 ++++---- test/json/json_encoding_test.rb | 6 ++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 79398951..942602b9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ### Unreleased +* Fix `IndexOutOfBoundsException` in the JRuby extension when encoding shared strings. + ### 2025-09-18 (2.14.0) * Add new `allow_duplicate_key` generator options. By default a warning is now emitted when a duplicated key is encountered. diff --git a/java/src/json/ext/SWARBasicStringEncoder.java b/java/src/json/ext/SWARBasicStringEncoder.java index 8021d73b..08cd2e47 100644 --- a/java/src/json/ext/SWARBasicStringEncoder.java +++ b/java/src/json/ext/SWARBasicStringEncoder.java @@ -24,14 +24,14 @@ void encode(ByteList src) throws IOException { int pos = 0; ByteBuffer bb = ByteBuffer.wrap(ptrBytes, 0, len); - while (pos + 8 <= len) { + while (ptr + pos + 8 <= len) { long x = bb.getLong(ptr + pos); if (skipChunk(x)) { pos += 8; continue; } - int chunkEnd = pos + 8; - while (pos < chunkEnd) { + int chunkEnd = ptr + pos + 8; + while (ptr + pos < chunkEnd) { int ch = Byte.toUnsignedInt(ptrBytes[ptr + pos]); int ch_len = ESCAPE_TABLE[ch]; if (ch_len > 0) { @@ -43,7 +43,7 @@ void encode(ByteList src) throws IOException { } } - if (pos + 4 <= len) { + if (ptr + pos + 4 <= len) { int x = bb.getInt(ptr + pos); if (skipChunk(x)) { pos += 4; diff --git a/test/json/json_encoding_test.rb b/test/json/json_encoding_test.rb index caf335d5..8dce81da 100644 --- a/test/json/json_encoding_test.rb +++ b/test/json/json_encoding_test.rb @@ -31,6 +31,12 @@ def test_generate assert_equal @generated, JSON.generate(@utf_16_data, ascii_only: true) end + def test_generate_shared_string + # Ref: https://github.com/ruby/json/issues/859 + s = "01234567890" + assert_equal '"234567890"', JSON.dump(s[2..-1]) + end + def test_unicode assert_equal '""', ''.to_json assert_equal '"\\b"', "\b".to_json