Commons Lang
  1. Commons Lang
  2. LANG-6

[lang] EqualsBuilder.append(Object[], Object[]) incorrectly checks that rhs[i] is instance of lhs[i]'s class

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0
    • Fix Version/s: 2.1
    • Component/s: None
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

      Description

      Append two arrays of any object type to an EqualsBuilder using EqualsBuilder.append(Object[],
      Object[]) – we'll call the first 'lhs' and the second 'rhs'. If, for any i, lhs[i] is not null, rhs[i] is not null,
      and rhs[i] is not of the same type as, or a subtype of, lhs[i], then the EqualsBuilder will return false.

      However, this behavior is incorrect. While rare, it is perfectly valid in Java to define an equals() method
      on a class A that will return true when passed in an object of some class B, where B is not the same as A
      nor a subtype of A. (A conceptual example is comparing a RGBColor to a CMYKColor, where RGBColor is
      not a subclass of CMYKColor, nor vice-versa. In this example, the EqualsBuilder will return false,
      whether the equals() method is defined on RGBColor to explicitly check CMYKColors, or even if you
      define a base-class Color.equals() method that does an abstract comparison.)

      To reproduce:

      public static class A {
      private int a;
      public A(int a)

      { this.a = a; }

      public boolean equals(Object o)

      { if (o == this) return true; if (o instanceof A) return this.a = ((A) o).getA(); if (o instanceof B) return this.a = ((B) o).getB(); return false; }

      public int getA()

      { return this.a; }

      }

      public static class B {
      private int b;
      public B(int b)

      { this.b = b; }

      public boolean equals(Object o)

      { if (o == this) return true; if (o instanceof A) return this.b = ((A) o).getA(); if (o instanceof B) return this.b = ((B) o).getB(); return false; }

      public int getB()

      { return this.b; }

      }

      Object[] x = new Object[]

      { new A(1) }

      ;
      Object[] y = new Object[]

      { new B(1) }

      ;

      System.err.println("x[0].equals(y[0])? " + x[0].equals(y[0]));
      System.err.println("Does EqualsBuilder think the arrays are equal? " + (new EqualsBuilder().append(x,
      y).isEquals()));

      This program will output:

      true
      false

      The attached patch adds to an existing unit-test case some code that proves the existence of this bug,
      and also fixes it. (It also fixes COM-1842.)

        Activity

        Hide
        Henri Yandell added a comment -

        2.1 released, closing.

        Show
        Henri Yandell added a comment - 2.1 released, closing.
        Hide
        ggregory@seagullsw.com added a comment -

        This issue is already fixed in CVS and should be the current nightly build. I
        have added a unit test EqualsBuilderTest.testUnrelatedClasses() which is almost
        identical to the example in this ticket.

        Show
        ggregory@seagullsw.com added a comment - This issue is already fixed in CVS and should be the current nightly build. I have added a unit test EqualsBuilderTest.testUnrelatedClasses() which is almost identical to the example in this ticket.
        Hide
        Andrew Geweke added a comment -

        See also COM-1842.

        Show
        Andrew Geweke added a comment - See also COM-1842 .
        Hide
        Andrew Geweke added a comment -

        Created an attachment (id=13984)
        This patch introduces testcases for, and fixes, bugs 33067 and 33069.

        Show
        Andrew Geweke added a comment - Created an attachment (id=13984) This patch introduces testcases for, and fixes, bugs 33067 and 33069.

          People

          • Assignee:
            Unassigned
            Reporter:
            Andrew Geweke
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development