This is an automated email from the ASF dual-hosted git repository.

RyanSkraba pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/main by this push:
     new cc134b3ff6 MINOR: [c++] reject lone low surrogate U+DFFF in JSON 
decoder (#3841)
cc134b3ff6 is described below

commit cc134b3ff6016d86a5f97798afc77ef1a47b7d73
Author: mohammed arib <[email protected]>
AuthorDate: Sun Jul 19 16:35:59 2026 +0530

    MINOR: [c++] reject lone low surrogate U+DFFF in JSON decoder (#3841)
    
    The lone-surrogate check used an exclusive upper bound (n < 0xdfff), so the 
last low surrogate U+DFFF slipped through and was emitted as the invalid UTF-8 
sequence ED BF BF; make the bound inclusive to match the trailing-surrogate 
validation in the same function.
---
 lang/c++/impl/json/JsonIO.cc |  2 +-
 lang/c++/test/JsonTests.cc   | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/lang/c++/impl/json/JsonIO.cc b/lang/c++/impl/json/JsonIO.cc
index 5f5fe8e3bc..a4a3f828c1 100644
--- a/lang/c++/impl/json/JsonIO.cc
+++ b/lang/c++/impl/json/JsonIO.cc
@@ -394,7 +394,7 @@ string JsonParser::decodeString(const string &s, bool 
binary) {
                             throw Exception("Invalid unicode sequence: {}", 
string(startSeq, it));
                         }
                         n = 0x10000 + (((n - 0xd800) << 10) | (m - 0xdc00));
-                    } else if (n >= 0xdc00 && n < 0xdfff) {
+                    } else if (n >= 0xdc00 && n <= 0xdfff) {
                         throw Exception("Invalid unicode sequence: {}", 
string(startSeq, it));
                     }
                     if (n < 0x80) {
diff --git a/lang/c++/test/JsonTests.cc b/lang/c++/test/JsonTests.cc
index afaa20f1ac..b57f7a7636 100644
--- a/lang/c++/test/JsonTests.cc
+++ b/lang/c++/test/JsonTests.cc
@@ -23,6 +23,7 @@
 #include <boost/test/unit_test.hpp>
 
 #include "../impl/json/JsonDom.hh"
+#include "Exception.hh"
 
 namespace avro {
 namespace json {
@@ -175,6 +176,14 @@ static void testObject2() {
     BOOST_CHECK_EQUAL(a[1].stringValue(), "v0");
 }
 
+// A low surrogate that is not preceded by a high surrogate is not a valid
+// code point and must be rejected, including the last one (U+DFFF).
+static void testLoneLowSurrogate() {
+    BOOST_CHECK_THROW(loadEntity(R"("\udc00")").stringValue(), Exception);
+    BOOST_CHECK_THROW(loadEntity(R"("\udffe")").stringValue(), Exception);
+    BOOST_CHECK_THROW(loadEntity(R"("\udfff")").stringValue(), Exception);
+}
+
 } // namespace json
 } // namespace avro
 
@@ -208,5 +217,7 @@ init_unit_test_suite(int /* argc */, char * /* argv */[]) {
     ts->add(BOOST_TEST_CASE(&avro::json::testObject1));
     ts->add(BOOST_TEST_CASE(&avro::json::testObject2));
 
+    ts->add(BOOST_TEST_CASE(&avro::json::testLoneLowSurrogate));
+
     return ts;
 }

Reply via email to