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

mgrigorov 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 20772be73 [AVRO-3945] Add missing bounds check in the loop (#2812)
20772be73 is described below

commit 20772be733a3762d821aba57284cd462610238c1
Author: Mikhail Koviazin <[email protected]>
AuthorDate: Mon Mar 25 13:18:52 2024 +0200

    [AVRO-3945] Add missing bounds check in the loop (#2812)
    
    * [AVRO-3945] Add missing bounds checks for extra increments in the loop
    
    This issue was found by cppcheck:
    
        impl/json/JsonIO.cc:319:66: warning: Missing bounds check for extra 
iterator increment in loop. [StlMissingComparison]
            for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
                                                                         ^
        impl/json/JsonIO.cc:350:37: note: Missing bounds check for extra 
iterator increment in loop.
                                char c = *++it;
                                            ^
        impl/json/JsonIO.cc:319:66: note: Missing bounds check for extra 
iterator increment in loop.
            for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
    
    The original implementation contained a for-loop that incremented an
    iterator on each iteration **and** if a backslash was found. This caused
    a situtation when a malicious string could cause an invalid memory access,
    because the iterator would reach **after** the `s.cend()` due to additional
    increments in the loop body.
    
    This commit fixes the issue.
    
    * build.sh: sort unittests and add forgotten tests
---
 lang/c++/build.sh            | 13 ++++++++-----
 lang/c++/impl/json/JsonIO.cc | 15 +++++++++++----
 lang/c++/test/JsonTests.cc   |  1 +
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/lang/c++/build.sh b/lang/c++/build.sh
index 81530ed0f..5eed350fa 100755
--- a/lang/c++/build.sh
+++ b/lang/c++/build.sh
@@ -86,14 +86,17 @@ case "$target" in
     (cmake -S. -Bbuild -D CMAKE_BUILD_TYPE=Debug -D AVRO_ADD_PROTECTOR_FLAGS=1 
&& cmake --build build \
       && ./build/buffertest \
       && ./build/unittest \
+      && ./build/AvrogencppTestReservedWords \
+      && ./build/AvrogencppTests \
       && ./build/CodecTests \
+      && ./build/CommonsSchemasTests \
       && ./build/CompilerTests \
-      && ./build/StreamTests \
-      && ./build/SpecificTests \
-      && ./build/AvrogencppTests \
       && ./build/DataFileTests   \
-      && ./build/SchemaTests   \
-      && ./build/CommonsSchemasTests)
+      && ./build/JsonTests \
+      && ./build/LargeSchemaTests \
+      && ./build/SchemaTests \
+      && ./build/SpecificTests \
+      && ./build/StreamTests)
     ;;
 
   xcode-test)
diff --git a/lang/c++/impl/json/JsonIO.cc b/lang/c++/impl/json/JsonIO.cc
index 62549484a..7f002ed99 100644
--- a/lang/c++/impl/json/JsonIO.cc
+++ b/lang/c++/impl/json/JsonIO.cc
@@ -316,10 +316,17 @@ JsonParser::Token JsonParser::tryString() {
 
 string JsonParser::decodeString(const string &s, bool binary) {
     string result;
-    for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
-        char ch = *it;
+    const auto readNextByte = [](string::const_iterator &it, const 
string::const_iterator &end) -> char {
+        if (it == end)
+            throw Exception("Unexpected EOF");
+        return *it++;
+    };
+    auto it = s.cbegin();
+    const auto end = s.cend();
+    while (it != end) {
+        char ch = *it++;
         if (ch == '\\') {
-            ch = *++it;
+            ch = readNextByte(it, end);
             switch (ch) {
                 case '"':
                 case '\\':
@@ -347,7 +354,7 @@ string JsonParser::decodeString(const string &s, bool 
binary) {
                     char e[4];
                     for (char &i : e) {
                         n *= 16;
-                        char c = *++it;
+                        char c = readNextByte(it, end);
                         i = c;
                         if (isdigit(c)) {
                             n += c - '0';
diff --git a/lang/c++/test/JsonTests.cc b/lang/c++/test/JsonTests.cc
index da9722f30..10a100540 100644
--- a/lang/c++/test/JsonTests.cc
+++ b/lang/c++/test/JsonTests.cc
@@ -68,6 +68,7 @@ TestData<const char *> stringData[] = {
     {R"("\/")", EntityType::String, "/", R"("\/")"},
     {R"("\u20ac")", EntityType::String, "\xe2\x82\xac", R"("\u20ac")"},
     {R"("\u03c0")", EntityType::String, "\xcf\x80", R"("\u03c0")"},
+    {R"("hello\n")", EntityType::String, "hello\n", R"("hello\n")"},
 };
 
 void testBool(const TestData<bool> &d) {

Reply via email to