bjlaub opened a new issue, #3562: URL: https://github.com/apache/logging-log4j2/issues/3562
## Description It's possible for `StatusData#getFormattedStatus()` to throw an `ArrayIndexOutOfBoundsException` when given a message with a non-null, 0-length `parameters` array. This happens because there is only a null check on `parameters`, but no bounds check. I discovered this very trivially by using slf4j + log4j with no extra configuration, which by default utilizes `DefaultConfiguration` with the new [`DefaultLayout`](https://github.com/apache/logging-log4j2/blob/2.x/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultLayout.java) which uses `StatusData` under the hood. The 0-length parameters array seems to be a result of a call to [`MutableLogEvent#setMessage`](https://github.com/apache/logging-log4j2/blob/2.x/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java#L220) which allocates a new Object array when swapping parameters with another ReusableMessage, though I haven't fully debugged that codepath to confirm if this is the source. Either way, the lack of a bounds check in `getFormattedStatus` seems wrong, and is trivial to cause the exception to be thrown. ## Configuration **Version:** 2.x branch (e.g. 2.25.0-SNAPSHOT) **Operating system:** macOS Sequoia 15.3 **JDK:**OpenJDK 64-Bit Server VM Corretto-17.0.6.10.1 (build 17.0.6+10-LTS, mixed mode, sharing) ## Logs See the unit test reproducers below. On 2.x, the test that directly calls getFormattedStatus it will fail with: ``` java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 0 at org.apache.logging.log4j.status.StatusData.getFormattedStatus(StatusData.java:182) ``` The test that logs via slf4j will not cause a failure, but will log the stacktrace for the ArrayIndexOutOfBoundsException instead of the actual log message: ``` 2025-03-20T14:23:21.756536Z main ERROR An exception occurred processing Appender DefaultConsole-2 java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 0 at org.apache.logging.log4j.status.StatusData.getFormattedStatus(StatusData.java:182) at org.apache.logging.log4j.core.config.DefaultLayout.toSerializable(DefaultLayout.java:50) at org.apache.logging.log4j.core.config.DefaultLayout.toByteArray(DefaultLayout.java:55) at org.apache.logging.log4j.core.config.DefaultLayout.encode(DefaultLayout.java:60) at org.apache.logging.log4j.core.config.DefaultLayout.encode(DefaultLayout.java:36) at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:227) at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:220) at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:211) at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:160) at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:133) at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:124) at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:88) at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:714) at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:672) at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:648) at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:584) at org.apache.logging.log4j.core.config.DefaultReliabilityStrategy.log(DefaultReliabilityStrategy.java:73) at org.apache.logging.log4j.core.Logger.log(Logger.java:187) at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2970) at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2922) at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2904) at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2653) at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:2393) at org.apache.logging.slf4j.Log4jLogger.error(Log4jLogger.java:293) at org.apache.logging.slf4j.Slf4jDefaultConfigurationTest.test_logging_with_default_configuration(Slf4jDefaultConfigurationTest.java:13) ``` ## Reproduction The following JUnit test demonstrates the problem: ``` public class StatusDataTest { @Test void test_getFormattedData_does_not_throw() { Message message = new Message() { @Override public String getFormattedMessage() { return "formatted"; } @Override public Object[] getParameters() { return Constants.EMPTY_OBJECT_ARRAY; } @Override public Throwable getThrowable() { return null; } }; StatusData statusData = new StatusData(null, Level.ERROR, message, null, null); // will throw on 2.x, but succeed on 2.24.3 assertThat(statusData.getFormattedStatus()).contains("formatted"); } } ``` It is also trivial to construct a test in log4j-slf4j-impl to trigger this codepath via slf4j: ``` import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Slf4jDefaultConfigurationTest { private static final Logger logger = LoggerFactory.getLogger(Slf4jDefaultConfigurationTest.class); @Test void test_logging_with_default_configuration() { // logs the ArrayIndexOutOfBoundsException, rather than the message logger.error("foo"); } } ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@logging.apache.org.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org