Repository: paritytech/parity-db (language: rust)

Issue:
Panic when doing duplicated references in the same transaction on a ref-counted btree
The following test:
```rust
#[test]
fn test_duplicated_reference_on_ref_counted_btree() {
	let tmp = tempdir().unwrap();
	let mut options = Options::with_columns(tmp.path(), 1);
	options.columns[0].ref_counted = true;
	options.columns[0].btree_index = true;
	let db = Db::open_or_create(&options).unwrap();
	db.commit_changes(vec![(0, Operation::Reference(vec![255])), (0, Operation::Reference(vec![255]))]).unwrap();
}
```

Fails with a panic:

```
thread 'db::tests::test_duplicated_reference_' panicked at 'assertion failed: changes[0].key() < changes[1].key()', src/btree/node.rs:76:17
```

(first test found with fuzzing!)


Discussion / hints:

Fix patch:
diff --git a/src/btree/node.rs b/src/btree/node.rs
index 26f75d70..f8ba3f50 100644
--- a/src/btree/node.rs
+++ b/src/btree/node.rs
@@ -64,16 +64,23 @@ impl Node {
 		log: &mut LogWriter,
 	) -> Result<(Option<(Separator, Child)>, bool)> {
 		loop {
-			if changes.len() > 1 {
-				if changes[0].key() == changes[1].key() &&
-					!changes[0].is_reference_ops() &&
-					!changes[1].is_reference_ops()
-				{
+			if changes.len() > 1 && !changes[0].is_reference_ops() {
+				let mut skip = false;
+				for next in changes[1..].iter() {
+					if changes[0].key() == next.key() {
+						if !next.is_reference_ops() {
+							skip = true;
+							break
+						}
+					} else {
+						break
+					}
+				}
+				if skip {
 					// TODO only when advancing (here rec call useless)
 					*changes = &changes[1..];
 					continue
 				}
-				debug_assert!(changes[0].key() < changes[1].key());
 			}
 			let r = match &changes[0] {
 				Operation::Set(key, value) =>


Test patch: