Skip to content

Internal fn encode_mut seems to be unsound #124

@anforowicz

Description

@anforowicz

I don't see how fn encode_mut (a safe function) guarantees the (implied) safety requirements of fn chunk_mut_unchecked:

fn encode_mut<B: Static<usize>, M: Static<bool>>(
bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8],
) {
debug_assert_eq!(output.len(), encode_len(bit, input.len()));
let enc = enc(bit.val());
let dec = dec(bit.val());
let n = input.len() / enc;
let bs = match bit.val() {
5 => 2,
6 => 4,
_ => 1,
};
vectorize(n, bs, |i| {
let input = unsafe { chunk_unchecked(input, enc, i) };
let output = unsafe { chunk_mut_unchecked(output, dec, i) };
encode_block(bit, msb, symbols, input, output);
});
encode_block(bit, msb, symbols, &input[enc * n ..], &mut output[dec * n ..]);
}

dec and i (on line 416) are produced by fn vectorize depending on n (derived from input on line 408) and bs (derived from bit on lines 409-413). There is no data dependency on output as far as I can tell. Therefore I don't see how fn encode_mut can guarantee dec * (i + 1) <= output.len() (the implied safety requirement of chunk_mut_unchecked). Therefore I think that fn encode_mut is unsound as currently written.

PS. This issue report is based on the audit from https://chromium-review.googlesource.com/c/chromium/src/+/6187726/comment/ae7a20dd_8c886e35/.

/cc @Manishearth
/cc @djmitche, @apasel422

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions