diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f04a29..e539164 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ `maxStringLength` is used in combination with `emptyPropertyExclusionEnabled=true`. (#55) +- Fix `ArrayIndexOutOfBoundsException` thrown when `stackTrace:text` produces + an output violating the truncation limit. (#57) + ### (2019-10-15) v0.21 - Add feature comparison matrix. diff --git a/README.md b/README.md index c0d0367..c594141 100644 --- a/README.md +++ b/README.md @@ -474,6 +474,7 @@ Let us try to answer some common questions: - [bakomchik](https://github.com/bakomchik) - [chrissydee](https://github.com/chrissydee) +- [Daniel Lundsgaard Skovenborg](https://github.com/waldeinburg) - [Eric Schwartz](https://github.com/emschwar) - [Felix Barnsteiner](https://github.com/felixbarny) - [Johann Schmitz](https://github.com/ercpe) diff --git a/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedPrintWriter.java b/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedPrintWriter.java index c15f7b3..6e14961 100644 --- a/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedPrintWriter.java +++ b/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedPrintWriter.java @@ -28,6 +28,10 @@ public int getCapacity() { return bufferedWriter.getCapacity(); } + public boolean isOverflow() { + return bufferedWriter.isOverflow(); + } + @Override public void close() { bufferedWriter.close(); diff --git a/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedWriter.java b/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedWriter.java index 90886eb..01b1d87 100644 --- a/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedWriter.java +++ b/layout/src/main/java/com/vlkan/log4j2/logstash/layout/util/BufferedWriter.java @@ -8,9 +8,12 @@ public final class BufferedWriter extends Writer { private int position; + private boolean overflow; + BufferedWriter(int capacity) { this.buffer = new char[capacity]; this.position = 0; + this.overflow = false; } char[] getBuffer() { @@ -25,10 +28,23 @@ int getCapacity() { return buffer.length; } + boolean isOverflow() { + return overflow; + } + @Override public void write(char[] source, int offset, int length) { - System.arraycopy(source, offset, buffer, position, length); - position += length; + if (!overflow) { + int limit = buffer.length - position; + if (length > limit) { + overflow = true; + System.arraycopy(source, offset, buffer, position, limit); + position = buffer.length; + } else { + System.arraycopy(source, offset, buffer, position, length); + position += length; + } + } } @Override @@ -37,6 +53,7 @@ public void flush() {} @Override public void close() { position = 0; + overflow = false; } } diff --git a/layout/src/test/java/com/vlkan/log4j2/logstash/layout/LogstashLayoutTest.java b/layout/src/test/java/com/vlkan/log4j2/logstash/layout/LogstashLayoutTest.java index 17f7eb7..7caae8b 100644 --- a/layout/src/test/java/com/vlkan/log4j2/logstash/layout/LogstashLayoutTest.java +++ b/layout/src/test/java/com/vlkan/log4j2/logstash/layout/LogstashLayoutTest.java @@ -1455,4 +1455,39 @@ public void test_maxStringLength_with_emptyPropertyExclusionEnabled() throws Exc } + @Test + public void test_StackTraceTextResolver_with_maxStringLength() throws Exception { + + // Create the event template. + ObjectNode eventTemplateRootNode = JSON_NODE_FACTORY.objectNode(); + eventTemplateRootNode.put("stackTrace", "${json:exception:stackTrace:text}"); + String eventTemplate = eventTemplateRootNode.toString(); + + // Create the layout. + int maxStringLength = eventTemplate.length(); + Configuration configuration = ConfigurationBuilderFactory.newConfigurationBuilder().build(); + LogstashLayout layout = LogstashLayout + .newBuilder() + .setConfiguration(configuration) + .setEventTemplate(eventTemplate) + .setMaxStringLength(maxStringLength) + .setStackTraceEnabled(true) + .build(); + + // Create the log event. + SimpleMessage message = new SimpleMessage("foo"); + LogEvent logEvent = Log4jLogEvent + .newBuilder() + .setLoggerName(LogstashLayoutTest.class.getSimpleName()) + .setMessage(message) + .setThrown(NonAsciiUtf8MethodNameContainingException.INSTANCE) + .build(); + + // Check the serialized event. + String serializedLogEvent = layout.toSerializable(logEvent); + JsonNode rootNode = OBJECT_MAPPER.readTree(serializedLogEvent); + assertThat(point(rootNode, "stackTrace").asText()).isNotBlank(); + + } + }