After reading corrupted history entry, keep reading older entries

Given a history like

    - cmd: echo OLD
      when: 1726157160
    \x00\x00\x00- cmd: echo leading NUL bytes
      when: 1726157160
    - cmd: echo NEW
      when: 1726157223

offset_of_next_item() happily records 3 items even though the second item
is corrupted.
decode_item() fails which makes the caller stop loading any older items --
we got knee capped.

Avoid this horrible failure mode by skipping over these items already in
offset computation. For now we still lose the corrupted item itself.

In future we should probably try to delete the NUL bytes or avoid the
corruption in the first place.

See #10300 and others.
This commit is contained in:
Johannes Altmanninger 2024-10-06 00:22:15 +02:00
parent 052e764f29
commit 1b9b893169

View file

@ -358,9 +358,7 @@ fn decode_item_fish_2_0(mut data: &[u8]) -> Option<HistoryItem> {
let (advance, line) = read_line(data);
let line = trim_start(line);
// Check this early *before* anything else.
if !line.starts_with(b"- cmd") {
return None;
}
assert!(line.starts_with(b"- cmd"));
let (_key, value) = extract_prefix_and_unescape_yaml(line)?;
@ -496,6 +494,15 @@ fn offset_of_next_item_fish_2_0(
continue;
}
if !line.starts_with(b"- cmd") {
FLOG!(
history,
"ignoring corrupted history entry around offset",
*cursor
);
continue;
}
// At this point, we know `line` is at the beginning of an item. But maybe we want to
// skip this item because of timestamps. A `None` cutoff means we don't care; if we do care,
// then try parsing out a timestamp.