[ 
https://issues.apache.org/jira/browse/LANG-1705?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17751225#comment-17751225
 ] 

Gary D. Gregory commented on LANG-1705:
---------------------------------------

That's an interesting use case. Thank you for letting us know. 

> commons-lang3:3.13.0 introduces breaking change in SerializationUtils
> ---------------------------------------------------------------------
>
>                 Key: LANG-1705
>                 URL: https://issues.apache.org/jira/browse/LANG-1705
>             Project: Commons Lang
>          Issue Type: Bug
>          Components: lang.*
>    Affects Versions: 3.13.0
>            Reporter: Rico Neubauer
>            Priority: Major
>         Attachments: SerializationTest.java
>
>
> Want to report a change in behavior, which is not necessarily a 
> bug/regression, but might get triggered by crude classes getting serialized.
> With this commit: 357951ff5c28dbd724611e8d41e23686f09a164a released in 3.13.0 
> SerializationUtils#clone changed a bit that it now makes a cast to the 
> expected type.
> This sounds reasonable, but might break existing code that serializes classes 
> that have parent-child dependencies and overwrite #writeObject in a certain 
> way.
> I'll provide a standalone test case below with comments that should make it 
> clear.
> Issue is in case writeObject changes the type of object that gets serialized, 
> then class obtained from in#readObject of the previously serialized object 
> will be different from the expected one.
> This most probably is a violation of:
> {noformat}
> "The object returned should be either of the same type as the object passed 
> in or an object that when read and resolved will result in an object of a 
> type that is compatible with all references to the object."
> https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/output.html{noformat}
> and also the contract of #clone, so could be treated as "told you", anyhow 
> such code may exist and then #clone will fail with:
> {code:java}
> java.lang.ClassCastException: Cannot cast SerializationTest$Parent to 
> SerializationTest$Child
>     at java.base/java.lang.Class.cast(Class.java:3605)
>     at 
> org.apache.commons.lang3.SerializationUtils.clone(SerializationUtils.java:148)
> {code}
> Standalone test for reproducing the issue with 3.13.0:
> {code:java}
> import static org.junit.Assert.assertEquals;
> import java.io.ObjectStreamException;
> import java.io.Serializable;
> import java.util.Objects;
> import org.apache.commons.lang3.SerializationUtils;
> import org.junit.Test;
> public class SerializationTest
> {
>     @Test
>     public void serializeParent() throws Exception
>     {
>         // this test will pass with any version
>         Parent parent = new Parent(true);
>         Parent clonedParent = SerializationUtils.clone(parent);
>         assertEquals(parent, clonedParent);
>     }
>     @Test
>     public void serializeChild() throws Exception
>     {
>         Child child = new Child(true);
>         // this test will pass with org.apache.commons:commons-lang3:3.12.0,
>         // but will fail with 3.13.0
>         Parent clonedChild = SerializationUtils.clone(child);
>         assertEquals(new Parent(true), clonedChild);
>     }
>     static class Parent implements Serializable
>     {
>         private static final long serialVersionUID = 1L;
>         protected boolean someField;
>         Parent(boolean someField)
>         {
>             this.someField = someField;
>         }
>         protected Parent(Parent parent)
>         {
>             this.someField = parent.someField;
>         }
>         /**
>          * protected modifier lets also child's serialization call this
>          */
>         protected Object writeReplace() throws ObjectStreamException
>         {
>             return new Parent(this);
>         }
>         @Override
>         public int hashCode()
>         {
>             return Objects.hash(someField);
>         }
>         @Override
>         public boolean equals(Object obj)
>         {
>             if (this == obj) return true;
>             if (obj == null) return false;
>             if (getClass() != obj.getClass()) return false;
>             Parent other = (Parent)obj;
>             return someField == other.someField;
>         }
>     }
>     static class Child extends Parent
>     {
>         private static final long serialVersionUID = 2L;
>         Child(boolean someField)
>         {
>             super(someField);
>         }
>     }
> }
> {code}
>  



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

Reply via email to