Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8284987

ImmutableCollections.ListItr can throw UnsupportedOperationException

    XMLWordPrintable

Details

    Description

      A DESCRIPTION OF THE PROBLEM :
      ImmutableCollections.ListItr is an implementation of a ListIterator used in immutable lists, and it's also used as the return value of iterator() calls.

      The implementation holds a boolean, isListIterator, that is true if the instance was created for a listIterator() call, false if it was for an iterator() call. It is used to throw UnsupportedOperationException() in case it was obtained as the result of a regular iterator().

      This is a problem for multiple reasons. First, the boolean would normally be unnecessary given that the return of the iterator() method is an Iterator, and therefore the ListIterator specific methods are not visible. However, a consumer could later do an instanceof ListIterator check in a given object, that would yield true, and therefore assume the class is a proper implementation of ListIterator. Even though the spec of ListIterator doesn't contemplate that these methods throw UnsupportedOperationException, they would.

      Suggestion to remove the boolean and checks for isListIterator.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      - Obtain an immutable List instance, for example by using List.of(E...).
      - Obtain an Iterator over that list by calling list.iterator()
      - Check for instanceof ListIterator (a check that could perfectly be in a library that you pass this too) and safely cast it to that
      - Call one of the following methods on the ListIterator: hasPrevious(), previous(), nextIndex(), previousIndex()

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The methods return an appropriate value and move the cursor if applicable.
      ACTUAL -
      An UnsupportedOperationException with no detail message is thrown.

      ---------- BEGIN SOURCE ----------
      var list = List.of(1, 2 , 3, 4);
      var iterator = list.iterator();
      if (iterator instanceof ListIterator<Integer> listIterator) {
          listIterator.hasPrevious(); // UOE
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Calling listIterator() on the List instance

      FREQUENCY : always


      Attachments

        Activity

          People

            smarks Stuart Marks
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: