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

Reply via email to