Uploaded image for project: 'XWiki Platform'
  1. XWiki Platform
  2. XWIKI-24779

FeedPlugin.EntriesComparator never sorts anything because it reads both objects from the first entry

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • Major
    • 18.8.0-rc-1
    • 17.10.12
    • Feed
    • None
    • Unit
    • Unknown
    • N/A
    • N/A

    Description

      FeedPlugin.EntriesComparator (in com.xpn.xwiki.plugin.feed.FeedPlugin) reads both of the objects it is asked to compare from the same entry:

      public int compare(com.xpn.xwiki.api.Object entry1, com.xpn.xwiki.api.Object entry2)
      {
          BaseObject bobj1 = entry1.getXWikiObject();
          BaseObject bobj2 = entry1.getXWikiObject();   // should be entry2
          ...
          return (-bobj1.getDateValue("date").compareTo(bobj2.getDateValue("date")));
      }
      

      What this breaks for users

      FeedPlugin#search(String, XWikiContext) is the search over aggregated feed articles: it collects the XWiki.FeedEntryClass objects matching the words the user typed and is meant to hand them back most-recent-first. Sorting them is the only thing EntriesComparator exists to do, and it does not do it.

      • Search results over aggregated feeds come back in an arbitrary order. com.xpn.xwiki.api.Object#getXWikiObject() returns the wrapped instance without copying it, so bobj1 and bobj2 are the same object: every comparison compares one article's date with itself, the comparator always returns 0, and Collections.sort(apiObjs, new EntriesComparator()) leaves the list exactly as it was. The HQL query behind the search carries no ORDER BY either, so what the user actually gets is raw database order: a three-year-old article can sit above this morning's one, and the order can differ between two runs of the same search or between two databases. Anyone using the feed aggregator to find recent news has to read the whole result list instead of the top of it.
      • The search fails outright for a caller without programming rights. getXWikiObject() returns null in that case, so the comparator throws a NullPointerException on bobj1.getDateValue("date") and the whole search errors out instead of returning results.

      What limits the blast radius: FeedPluginApi does not expose search, so the method is only reachable from Java code (this plugin and third-party plugins), not from wiki scripts. The feed plugin is also deprecated legacy code. The fix is therefore low priority — but EntriesComparator is a public class that third-party code can use as a comparator in its own right, where it will silently sort nothing.

      Origin

      The typo dates back to commit d3ede03523a ("[misc] Introduce generics", 2009), which introduced the two bobj locals; before that the code correctly used entry1 and entry2.

      Attachments

        Activity

          People

            vmassol Vincent Massol
            vmassol Vincent Massol
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: