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;
}