1. XStream
  2. XSTR-757

Deserialized TreeSet does not honor remove(Object) return value contract


    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 1.4.5
    • Fix Version/s: 1.4.8
    • Component/s: Converters
    • Labels:
    • JDK version and platform:
      Oracle JDK 7u60


      The following test case passes when run against XStream 1.4.4, as expected:

      import com.thoughtworks.xstream.XStream;
      import java.util.Set;
      import java.util.TreeSet;
      import org.junit.Test;
      import static org.junit.Assert.*;
      public class BugTest {
          @Test public void bug() {
              Set<Integer> s = new TreeSet<>();
              XStream xs = new XStream();
              s = (Set<Integer>) xs.fromXML(xs.toXML(s));
              assertTrue(s.remove(17)); // fails in 1.4.5+

      But it fails in 1.4.5 and later (including 1.4.7): remove returns false against contract. In a debugger,

      private transient NavigableMap<E,Object> m;
      private static final Object PRESENT = new Object();
      public boolean remove(Object o) {
          return m.remove(o)==PRESENT;

      When the bug occurs, m is 17=17 rather than 17=PRESENT. Presumably this is due to this code in TreeSetConverter:

      public boolean add(Object object) {
          return target.put(object, object) != null;

      1.4.4 has the same, but sortedMapField is null (because !JVM.hasOptimizedTreeSetAddAll()) so this code is not used.

      I am marking this as a high priority despite the possibility of workarounds once the bug is known, because there is no visible error during deserialization, yet the faulty collection then appears deep inside program logic and can lead to subtle bugs. (And in a large project using XStream extensively it is impossible to know who all might be using TreeSet.) I presume the only workaround is to replace TreeSetConverter with a working version.


        • Assignee:
          Jörg Schaible
          Jesse Glick
        • Votes:
          0 Vote for this issue
          2 Start watching this issue


          • Created: