Fix UnboundedFifoBuffer iterator remove bug causing ArrayIndexOutOfBounds

bug 35733, from Andreas Schlosser

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@219316 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Colebourne 2005-07-16 11:17:02 +00:00
parent 1fa2dd8d12
commit e1c5f7fb49
6 changed files with 547 additions and 17 deletions

View File

@ -86,6 +86,7 @@ If this causes major headaches to anyone please contact commons-dev at jakarta.a
<li>AbstractMapBag.BagIterator.remove - Removing the last entry used to break the class invariants [35747]</li>
<li>BoundedFifoBuffer/CircularFifoBuffer - Fix serialization to work in case where buffer serialized when full [31433]</li>
<li>BoundedFifoBuffer - Fix iterator remove bug causing ArrayIndexOutOfBounds error [33071]</li>
<li>UnboundedFifoBuffer - Fix iterator remove bug causing ArrayIndexOutOfBounds error [35733]</li>
<li>IteratorChain.remove() - Fix to avoid IllegalStateException when one of the underlying iterators is a FilterIterator [34267]</li>
<li>ExtendedProperties.convertProperties() - Fix to handle default properties maps correctly [32204]</li>
<li>Add casts to avoid some JDK1.5 compilation warnings [35474]</li>

View File

@ -300,6 +300,9 @@
<contributor>
<name>Jon Schewe</name>
</contributor>
<contributor>
<name>Andreas Schlosser</name>
</contributor>
<contributor>
<name>Christian Siefkes</name>
</contributor>

View File

@ -49,6 +49,7 @@ import java.util.NoSuchElementException;
* @author Berin Loritsch
* @author Paul Jack
* @author Stephen Colebourne
* @author Andreas Schlosser
*/
public class UnboundedFifoBuffer extends AbstractCollection implements Buffer {
@ -254,15 +255,10 @@ public class UnboundedFifoBuffer extends AbstractCollection implements Buffer {
}
// Other elements require us to shift the subsequent elements
int i = lastReturnedIndex + 1;
int i = increment(lastReturnedIndex);
while (i != m_tail) {
if (i >= m_buffer.length) {
m_buffer[i - 1] = m_buffer[0];
i = 0;
} else {
m_buffer[i - 1] = m_buffer[i];
i++;
}
m_buffer[decrement(i)] = m_buffer[i];
i = increment(i);
}
lastReturnedIndex = -1;

View File

@ -294,15 +294,10 @@ public class UnboundedFifoBuffer extends AbstractCollection implements Buffer, S
}
// Other elements require us to shift the subsequent elements
int i = lastReturnedIndex + 1;
int i = increment(lastReturnedIndex);
while (i != tail) {
if (i >= buffer.length) {
buffer[i - 1] = buffer[0];
i = 0;
} else {
buffer[i - 1] = buffer[i];
i++;
}
buffer[decrement(i)] = buffer[i];
i = increment(i);
}
lastReturnedIndex = -1;

View File

@ -142,5 +142,272 @@ public class TestUnboundedFifoBuffer extends AbstractTestCollection {
}
fail();
}
}
//-----------------------------------------------------------------------
public void testInternalStateAdd() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(2);
assertEquals(3, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(0, test.m_tail);
test.add("A");
assertEquals(3, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(1, test.m_tail);
test.add("B");
assertEquals(3, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("C"); // forces m_buffer increase
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(4, test.m_tail);
}
public void testInternalStateAddWithWrap() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(0, test.m_tail);
test.add("A");
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(1, test.m_tail);
test.add("B");
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("C");
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.remove("A");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
test.remove("B");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
}
public void testInternalStateRemove1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.remove("A");
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(4, test.m_tail);
}
public void testInternalStateRemove2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.remove("B");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemove1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
Iterator it = test.iterator();
it.next();
it.remove();
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(4, test.m_tail);
}
public void testInternalStateIteratorRemove2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
Iterator it = test.iterator();
it.next();
it.next();
it.remove();
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(0, test.m_tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(0, test.m_tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
assertEquals("C", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd3() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(0, test.m_tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
assertEquals("C", it.next());
assertEquals("D", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemoveWithWrap1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(3, test.m_head);
assertEquals(1, test.m_tail);
}
public void testInternalStateIteratorRemoveWithWrap2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
assertEquals("D", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
}
public void testInternalStateIteratorRemoveWithWrap3() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
assertEquals("D", it.next());
assertEquals("E", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
}
}

View File

@ -144,6 +144,274 @@ public class TestUnboundedFifoBuffer extends AbstractTestCollection {
fail();
}
//-----------------------------------------------------------------------
public void testInternalStateAdd() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(2);
assertEquals(3, test.buffer.length);
assertEquals(0, test.head);
assertEquals(0, test.tail);
test.add("A");
assertEquals(3, test.buffer.length);
assertEquals(0, test.head);
assertEquals(1, test.tail);
test.add("B");
assertEquals(3, test.buffer.length);
assertEquals(0, test.head);
assertEquals(2, test.tail);
test.add("C"); // forces buffer increase
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(3, test.tail);
test.add("D");
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(4, test.tail);
}
public void testInternalStateAddWithWrap() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
assertEquals(4, test.buffer.length);
assertEquals(0, test.head);
assertEquals(0, test.tail);
test.add("A");
assertEquals(4, test.buffer.length);
assertEquals(0, test.head);
assertEquals(1, test.tail);
test.add("B");
assertEquals(4, test.buffer.length);
assertEquals(0, test.head);
assertEquals(2, test.tail);
test.add("C");
assertEquals(4, test.buffer.length);
assertEquals(0, test.head);
assertEquals(3, test.tail);
test.remove("A");
assertEquals(4, test.buffer.length);
assertEquals(1, test.head);
assertEquals(3, test.tail);
test.remove("B");
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(3, test.tail);
test.add("D");
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(0, test.tail);
test.add("E");
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(1, test.tail);
}
public void testInternalStateRemove1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(3, test.tail);
test.remove("A");
assertEquals(5, test.buffer.length);
assertEquals(1, test.head);
assertEquals(3, test.tail);
test.add("D");
assertEquals(5, test.buffer.length);
assertEquals(1, test.head);
assertEquals(4, test.tail);
}
public void testInternalStateRemove2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(3, test.tail);
test.remove("B");
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(2, test.tail);
test.add("D");
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(3, test.tail);
}
public void testInternalStateIteratorRemove1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(3, test.tail);
Iterator it = test.iterator();
it.next();
it.remove();
assertEquals(5, test.buffer.length);
assertEquals(1, test.head);
assertEquals(3, test.tail);
test.add("D");
assertEquals(5, test.buffer.length);
assertEquals(1, test.head);
assertEquals(4, test.tail);
}
public void testInternalStateIteratorRemove2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
Iterator it = test.iterator();
it.next();
it.next();
it.remove();
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(2, test.tail);
test.add("D");
assertEquals(5, test.buffer.length);
assertEquals(0, test.head);
assertEquals(3, test.tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.buffer.length);
assertEquals(1, test.head);
assertEquals(0, test.tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
it.remove();
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(0, test.tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.buffer.length);
assertEquals(1, test.head);
assertEquals(0, test.tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
assertEquals("C", it.next());
it.remove();
assertEquals(4, test.buffer.length);
assertEquals(1, test.head);
assertEquals(3, test.tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd3() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.buffer.length);
assertEquals(1, test.head);
assertEquals(0, test.tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
assertEquals("C", it.next());
assertEquals("D", it.next());
it.remove();
assertEquals(4, test.buffer.length);
assertEquals(1, test.head);
assertEquals(3, test.tail);
}
public void testInternalStateIteratorRemoveWithWrap1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(1, test.tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
it.remove();
assertEquals(4, test.buffer.length);
assertEquals(3, test.head);
assertEquals(1, test.tail);
}
public void testInternalStateIteratorRemoveWithWrap2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(1, test.tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
assertEquals("D", it.next());
it.remove();
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(0, test.tail);
}
public void testInternalStateIteratorRemoveWithWrap3() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(1, test.tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
assertEquals("D", it.next());
assertEquals("E", it.next());
it.remove();
assertEquals(4, test.buffer.length);
assertEquals(2, test.head);
assertEquals(0, test.tail);
}
//-----------------------------------------------------------------------
public String getCompatibilityVersion() {
return "3.1";
}