[ 
https://issues.apache.org/jira/browse/LOG4J2-3680?focusedWorklogId=903722&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-903722
 ]

ASF GitHub Bot logged work on LOG4J2-3680:
------------------------------------------

                Author: ASF GitHub Bot
            Created on: 05/Feb/24 20:31
            Start Date: 05/Feb/24 20:31
    Worklog Time Spent: 10m 
      Work Description: vy commented on code in PR #2259:
URL: https://github.com/apache/logging-log4j2/pull/2259#discussion_r1478875579


##########
log4j-api/src/main/java/org/apache/logging/log4j/util/internal/SerializationUtil.java:
##########
@@ -133,5 +139,62 @@ public static void assertFiltered(final 
java.io.ObjectInputStream stream) {
         }
     }
 
+    /**
+     * Gets the class name of an array component recursively.
+     * <p>
+     *     If {@code clazz} is not an array class its name is returned.
+     * </p>
+     * @param clazz the binary name of a class.
+     */
+    public static String stripArray(final Class<?> clazz) {
+        Class<?> currentClazz = clazz;
+        while (currentClazz.isArray()) {
+            currentClazz = currentClazz.getComponentType();
+        }
+        return currentClazz.getName();
+    }
+
+    /**
+     * Gets the class name of an array component recursively.
+     * <p>
+     *     If {@code name} is not the name of an array class it is returned 
unchanged.
+     * </p>
+     * @param name the name of a class.
+     * @see Class#getName()
+     */
+    public static String stripArray(final String name) {
+        int offset;
+        for (offset = 0; offset < name.length() && name.charAt(offset) == '['; 
offset++) {}
+        if (offset == 0) {
+            return name;
+        }
+        // Reference types
+        if (name.charAt(offset) == 'L') {
+            return name.substring(offset + 1, name.length() - 1);
+        }
+        // Primitive classes
+        switch (name.substring(offset)) {
+            case "Z":
+                return "boolean";
+            case "B":
+                return "byte";
+            case "C":
+                return "char";
+            case "D":
+                return "double";
+            case "F":
+                return "float";
+            case "I":
+                return "int";
+            case "J":
+                return "long";
+            case "S":
+                return "short";
+            default:

Review Comment:
   Shouldn't we be throwing an exception? In particular, we are in pretty 
dangerous waters of serialization...



##########
log4j-api/src/main/java/org/apache/logging/log4j/util/internal/SerializationUtil.java:
##########
@@ -133,5 +139,62 @@ public static void assertFiltered(final 
java.io.ObjectInputStream stream) {
         }
     }
 
+    /**
+     * Gets the class name of an array component recursively.
+     * <p>
+     *     If {@code clazz} is not an array class its name is returned.
+     * </p>
+     * @param clazz the binary name of a class.
+     */
+    public static String stripArray(final Class<?> clazz) {
+        Class<?> currentClazz = clazz;
+        while (currentClazz.isArray()) {
+            currentClazz = currentClazz.getComponentType();
+        }
+        return currentClazz.getName();
+    }
+
+    /**
+     * Gets the class name of an array component recursively.
+     * <p>
+     *     If {@code name} is not the name of an array class it is returned 
unchanged.
+     * </p>
+     * @param name the name of a class.
+     * @see Class#getName()
+     */
+    public static String stripArray(final String name) {
+        int offset;
+        for (offset = 0; offset < name.length() && name.charAt(offset) == '['; 
offset++) {}

Review Comment:
   Why not simply using `String#indexOf(char)` instead?





Issue Time Tracking
-------------------

    Worklog Id:     (was: 903722)
    Time Spent: 20m  (was: 10m)

> Some log events are no longer serialized correctly
> --------------------------------------------------
>
>                 Key: LOG4J2-3680
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-3680
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.22.0
>            Reporter: Peter De Maeyer
>            Assignee: Piotr Karwasz
>            Priority: Major
>          Time Spent: 20m
>  Remaining Estimate: 0h
>
> We noticed a regression between 2.21.1 and 2.22.0 in the serilialization of 
> log events. The below test succeeds with 2.21.1, but fails with 2.22.0. I had 
> a look at the source code, and I think it's because of changes in the 
> {{ObjectMessage.read/writeObject}} implementation.
> {code:java}
> import static org.apache.logging.log4j.LogManager.getLogger;
> import static org.junit.jupiter.api.Assertions.assertEquals;
> import java.io.ByteArrayInputStream;
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.ObjectInputStream;
> import java.io.ObjectOutputStream;
> import java.io.Serializable;
> import java.util.ArrayList;
> import java.util.List;
> import org.apache.logging.log4j.core.Appender;
> import org.apache.logging.log4j.core.ErrorHandler;
> import org.apache.logging.log4j.core.Layout;
> import org.apache.logging.log4j.core.LogEvent;
> import org.apache.logging.log4j.core.Logger;
> import org.junit.jupiter.api.AfterEach;
> import org.junit.jupiter.api.BeforeEach;
> import org.junit.jupiter.api.Test;
> class Log4jSerializationTest {
>     private final Logger logger = (Logger) 
> getLogger(Log4jSerializationTest.class);
>     private final RecordingAppender appender = new 
> RecordingAppender(Log4jSerializationTest.class.getName());
>     @BeforeEach
>     void addRecordingAppender() {
>         appender.start();
>         logger.addAppender(appender);
>     }
>    @AfterEach
>     void removeRecordingAppender() {
>         logger.removeAppender(appender);
>         appender.stop();
>     }
>     @Test
>     void logEventSerialization() {
>         RuntimeException exception = new RuntimeException("induced by test");
>         logger.error(exception, exception);
>         LogEvent event = appender.getEvents().get(0);
>         assertEquals(RuntimeException.class.getName() + ": induced by test", 
> event.getMessage().getFormattedMessage());
>     }
>     static class RecordingAppender implements Appender {
>         private final List<LogEvent> events = new ArrayList();
>         private State state = State.STOPPED;
>         private final String name;
>         private ErrorHandler handler;
>         public RecordingAppender(String name) {
>             this.name = name;
>         }
>         @Override
>         public State getState() {
>             return state;
>         }
>         @Override
>         public void initialize() {
>             state = State.INITIALIZED;
>         }
>         @Override
>         public boolean isStarted() {
>             return state == State.STARTED;
>         }
>         @Override
>         public boolean isStopped() {
>             return !isStarted();
>         }
>         @Override
>         public void start() {
>             events.clear();
>             state = State.STARTED;
>         }
>         @Override
>         public void stop() {
>             events.clear();
>             state = State.STOPPED;
>         }
>         @Override
>         public synchronized void append(LogEvent event) {
>             // The event is a mutable one, Log4j2 emits the same event 
> instance but changes the message each time.
>             // If we want to hold on to the event details, we need to clone 
> the event.
>             // LogEvent is not an instance of Cloneable, but it IS an 
> instance of Serializable.
>             // So we clone by serializing and deserializing.
>             ByteArrayOutputStream out = new ByteArrayOutputStream();
>             try (ObjectOutputStream objectOut = new ObjectOutputStream(out)) {
>                 objectOut.writeObject(event);
>             } catch (IOException e) {
>                 throw new RuntimeException(e);
>             }
>             LogEvent clone;
>             try (ObjectInputStream objectInput = new ObjectInputStream(new 
> ByteArrayInputStream(out.toByteArray()))) {
>                 clone = (LogEvent) objectInput.readObject();
>             } catch (IOException | ClassNotFoundException e) {
>                 throw new RuntimeException(e);
>             }
>             events.add(clone);
>         }
>         @Override
>         public ErrorHandler getHandler() {
>             return handler;
>         }
>         @Override
>         public Layout<? extends Serializable> getLayout() {
>             return null;
>         }
>         @Override
>         public String getName() {
>             return name;
>         }
>         @Override
>         public boolean ignoreExceptions() {
>             return true;
>         }
>         @Override
>         public void setHandler(ErrorHandler handler) {
>             this.handler = handler;
>         }
>         public synchronized List<LogEvent> getEvents() {
>             return events;
>         }
>     }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to