Details
-
Bug
-
Resolution: Fixed
-
Major
-
17.10.12
-
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.