diff --git a/.changelog/2698.bugfix.md b/.changelog/2698.bugfix.md new file mode 100644 index 00000000000..537d6e74229 --- /dev/null +++ b/.changelog/2698.bugfix.md @@ -0,0 +1 @@ +go/storage/mkvs: Fix removal crash when key is too short diff --git a/go/storage/mkvs/urkel/remove.go b/go/storage/mkvs/urkel/remove.go index b1022b99130..d27f6d2264e 100644 --- a/go/storage/mkvs/urkel/remove.go +++ b/go/storage/mkvs/urkel/remove.go @@ -72,7 +72,10 @@ func (t *tree) doRemove( var changed bool var existing []byte - if key.BitLength() == bitLength { + if key.BitLength() < bitLength { + // Lookup key is too short for the current n.Label, so it doesn't exist. + return ptr, false, nil, nil + } else if key.BitLength() == bitLength { n.LeafNode, changed, existing, err = t.doRemove(ctx, n.LeafNode, bitLength, key, depth) } else if key.GetBit(bitLength) { n.Right, changed, existing, err = t.doRemove(ctx, n.Right, bitLength, key, depth+1) diff --git a/runtime/src/storage/mkvs/urkel/tree/remove.rs b/runtime/src/storage/mkvs/urkel/tree/remove.rs index d7da9663779..0e8b6bfa108 100644 --- a/runtime/src/storage/mkvs/urkel/tree/remove.rs +++ b/runtime/src/storage/mkvs/urkel/tree/remove.rs @@ -69,32 +69,27 @@ impl UrkelTree { if let NodeBox::Internal(ref mut n) = *node_ref.borrow_mut() { // Remove from internal node and recursively collapse the branch, if // needed. - let (new_child, c, o) = if key.bit_length() == bit_depth + n.label_bit_length { + let bit_length = bit_depth + n.label_bit_length; + + if key.bit_length() < bit_length { + // Lookup key is too short for the current n.Label, so it doesn't exist. + return Ok((ptr.clone(), false, None)); + } + + let (new_child, c, o) = if key.bit_length() == bit_length { self._remove(ctx, n.leaf_node.clone(), bit_depth, key, depth)? - } else if key.get_bit(bit_depth + n.label_bit_length) { - self._remove( - ctx, - n.right.clone(), - bit_depth + n.label_bit_length, - key, - depth + 1, - )? + } else if key.get_bit(bit_length) { + self._remove(ctx, n.right.clone(), bit_length, key, depth + 1)? } else { - self._remove( - ctx, - n.left.clone(), - bit_depth + n.label_bit_length, - key, - depth + 1, - )? + self._remove(ctx, n.left.clone(), bit_length, key, depth + 1)? }; changed = c; old_val = o; - if key.bit_length() == bit_depth + n.label_bit_length { + if key.bit_length() == bit_length { n.leaf_node = new_child; - } else if key.get_bit(bit_depth + n.label_bit_length) { + } else if key.get_bit(bit_length) { n.right = new_child; } else { n.left = new_child;