GNOME Bugzilla – Bug 769035
[TrackerPriorityQueue] Bug in "tracker_priority_queue_foreach_remove" mismatch between list iterator and priority segment
Last modified: 2016-08-23 10:48:31 UTC
If an element is at the end of a priority segment and compare_func returns TRUE, we end up with a mismatch between the priority segment iterator and the list iterator. This can potentially corrupt the priority queue. What happens is the following: 1.- Before calling compare_func we do: GList *elem; elem = list; list = list->next; 2.- (compare_func) (elem->data, compare_user_data) returns TRUE 3.- If elem is at the tail of a segment then we do: segment->last_elem = elem->prev; At this point we can be sure that 'list' point to the head of the next priority segment (if there is one) 4.- The segment iterator remains unchanged So what happens next is that from this point on we compare list elements to a segment we've already gone through. So none of the elem == segment->* will ever be true. I just found this bug recently, I haven't really found the functional impact of this behaviour.
You are right, this bug is unlikely to happen, but is indeed possible. I'm attaching a patch fixing this that will be pushed to the master branch so far.
Created attachment 333984 [details] [review] libtracker-miner: Move to next priority queue segment after deleting tail If the tail element of a segment is being removed, we didn't move on to the next one, so accounting of subsequent segments might get broken if further elements are removed that are the head or the tail of a segment. Also, just do the "jump to next segment" bit generic, so the affected paths just turn on a fetch_segment boolean flag.
Thanks for spotting! I've just pushed the patch. Attachment 333984 [details] pushed as cbad8fe - libtracker-miner: Move to next priority queue segment after deleting tail