vigna / fastutil

fastutil extends the Java™ Collections Framework by providing type-specific maps, sets, lists and queues.
Apache License 2.0
1.81k stars 199 forks source link

removeLast is not properly resetting head #282

Closed Z-Kris closed 1 year ago

Z-Kris commented 1 year ago

(Code in Kotlin)

val collection = ObjectLinkedOpenHashSet<Any>()
collection.add("test")
collection.removeLast()
println(collection) // {}
val iterator = collection.iterator()
println(iterator.hasNext()) // true

The removeLast() function call on an ObjectLinkedOpenHashSet fails to reset the first variable, which causes the iterator to think there are elements still leftover even though the collection is empty. I have not tested this with any other collection type or version, others may experience similar issues. The removeFirst() function does not have this issue for reference.

Here's an image of the output of running the above code with a debugger, printing the first variable which has not been reset: image

vigna commented 1 year ago

Wow, this is really a good catch. The bug went unnoticed for >20 years. The bug is symmetric in removeFirst() and removeLast(), but the only way to unleash a bad behavior is through iteration, and iteration for the time being is forward only. The bug is that those methods contain a simplified version of fixPointers(), as written in the comments, but the simplified version forgot that the case of just one element is special in fixPointer(). I fixed this but if you send me by email or write here your real name I will add a thanks to the CHANGES file.

vigna commented 1 year ago

I haven't received anything—so no thanks.