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

vy pushed a commit to branch fix/2.24.x/JTL-StackTraceStringResolver
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit f9402ed2f72aa0dba6fe6b2f3a796a1e7c16e6fb
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Mon Nov 18 09:31:19 2024 +0100

    Fix off-by-one in `StackTraceStringResolver` (#3194)
---
 .../resolver/StackTraceStringResolverTest.java     | 63 ++++++++++++++++++++++
 .../json/resolver/StackTraceStringResolver.java    |  5 +-
 .../3211_fix_JTL_StackTraceStringResolver.xml      |  8 +++
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git 
a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolverTest.java
 
b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolverTest.java
index 430d6de646..dd3b371e10 100644
--- 
a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolverTest.java
+++ 
b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolverTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.layout.template.json.resolver;
 
+import static java.util.Collections.singletonList;
 import static 
org.apache.logging.log4j.layout.template.json.TestHelpers.CONFIGURATION;
 import static 
org.apache.logging.log4j.layout.template.json.TestHelpers.JAVA_BASE_PREFIX;
 import static org.apache.logging.log4j.layout.template.json.TestHelpers.asMap;
@@ -40,6 +41,7 @@ import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
 import 
org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults;
+import 
org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter;
 import org.apache.logging.log4j.util.Constants;
 import org.assertj.core.api.AbstractStringAssert;
 import org.junit.jupiter.api.Nested;
@@ -593,6 +595,67 @@ class StackTraceStringResolverTest {
         private String matchingRegex(final String string) {
             return "[" + string.charAt(0) + "]" + 
Pattern.quote(string.substring(1));
         }
+
+        @Test
+        void should_not_fail_on_truncated_output_not_ending_with_newline() {
+
+            // Try to find an exception whose truncated stack trace does not 
end with a newline
+            final int maxStringLength = 100;
+            final float maxByteCountPerChar =
+                    
JsonTemplateLayoutDefaults.getCharset().newEncoder().maxBytesPerChar();
+            final int maxStringByteCount =
+                    Math.toIntExact(Math.round(Math.ceil(maxByteCountPerChar * 
maxStringLength)));
+            final TruncatingBufferedPrintWriter writer = 
TruncatingBufferedPrintWriter.ofCapacity(maxStringByteCount);
+            Exception exception;
+            String message = "m";
+            do {
+                exception = new Exception(message);
+                exception.printStackTrace(writer);
+                if (writer.truncated() && writer.buffer()[writer.length() - 1] 
!= '\n') {
+                    break;
+                }
+                writer.close();
+                message += "m";
+            } while (true);
+
+            // Create the event template
+            final String eventTemplate = writeJson(asMap(
+                    "ex",
+                    asMap(
+                            "$resolver",
+                            "exception",
+                            "field",
+                            "stackTrace",
+                            "stackTrace",
+                            asMap(
+                                    "stringified",
+                                    asMap(
+                                            "truncation",
+                                            asMap(
+                                                    "suffix",
+                                                    TRUNCATION_SUFFIX,
+                                                    "pointMatcherStrings",
+                                                    singletonList("this string 
shouldn't match with anything")))))));
+
+            // Create the layout
+            final JsonTemplateLayout layout = JsonTemplateLayout.newBuilder()
+                    .setConfiguration(CONFIGURATION)
+                    .setEventTemplate(eventTemplate)
+                    .setMaxStringLength(maxStringLength)
+                    .setStackTraceEnabled(true)
+                    .build();
+
+            // Create the log event
+            final LogEvent logEvent =
+                    Log4jLogEvent.newBuilder().setThrown(exception).build();
+
+            // Check the serialized event
+            usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+                final int expectedStackTraceLength = maxStringLength + 
TRUNCATION_SUFFIX.length();
+                final String stackTrace = accessor.getString("ex");
+                
assertThat(stackTrace).hasSizeLessThan(expectedStackTraceLength);
+            });
+        }
     }
 
     @Test
diff --git 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolver.java
 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolver.java
index ebd34a3a47..077bf3d359 100644
--- 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolver.java
+++ 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolver.java
@@ -251,13 +251,14 @@ final class StackTraceStringResolver implements 
StackTraceResolver {
 
     private static int findLineStartIndex(final CharSequence buffer, final int 
startIndex, final int endIndex) {
         char prevChar = '-';
-        for (int i = startIndex; i <= endIndex; i++) {
+        int i = startIndex;
+        for (; i < endIndex; i++) {
             if (prevChar == '\n') {
                 return i;
             }
             prevChar = buffer.charAt(i);
         }
-        return -1;
+        return prevChar == '\n' ? i : -1;
     }
 
     private static int findMatchingIndex(
diff --git a/src/changelog/.2.x.x/3211_fix_JTL_StackTraceStringResolver.xml 
b/src/changelog/.2.x.x/3211_fix_JTL_StackTraceStringResolver.xml
new file mode 100644
index 0000000000..e28bdbc207
--- /dev/null
+++ b/src/changelog/.2.x.x/3211_fix_JTL_StackTraceStringResolver.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns="https://logging.apache.org/xml/ns";
+       xsi:schemaLocation="https://logging.apache.org/xml/ns 
https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="fixed">
+  <issue id="3211" link="https://github.com/apache/logging-log4j2/pull/3211"/>
+  <description format="asciidoc">Fix `ArrayIndexOutOfBoundsException` in JSON 
Template Layout truncated exception resolver</description>
+</entry>

Reply via email to