While working on porting aHash to https://github.com/inko-lang/inko I ran into the following:
|
fn write(&mut self, input: &[u8]) { |
|
let mut data = input; |
|
let length = data.len() as u64; |
|
//Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input. |
|
self.buffer = self.buffer.wrapping_add(length).wrapping_mul(MULTIPLE); |
|
//A 'binary search' on sizes reduces the number of comparisons. |
|
if data.len() > 8 { |
|
if data.len() > 16 { |
|
let tail = data.read_last_u128(); |
|
self.large_update(tail); |
|
while data.len() > 16 { |
|
let (block, rest) = data.read_u128(); |
|
self.large_update(block); |
|
data = rest; |
|
} |
|
} else { |
|
self.large_update([data.read_u64().0, data.read_last_u64()].convert()); |
|
} |
|
} else { |
|
let value = read_small(data); |
|
self.large_update(value.convert()); |
|
} |
|
} |
Specifically the following part appears problematic, at least at first sight:
|
while data.len() > 16 { |
|
let (block, rest) = data.read_u128(); |
|
self.large_update(block); |
|
data = rest; |
|
} |
Imagine the input buffer is 18 bytes long. The following condition is then true:
Which means it runs this:
|
let (block, rest) = data.read_u128(); |
|
self.large_update(block); |
|
data = rest; |
The read_u128 will then return (16 bytes of data, 2 bytes of data). Because of the data = rest assignment, the next hit of while data.len() > 16 translates into 2 > 16 and thus the loop isn't run.
Or more precisely, if the input size is not a multiple of 16 then up to 15 trailing bytes of input are not hashed.
I have a hard time imagining that this is in fact desired. Should that entire method not run in a loop to account for those trailing 15 bytes, or did I perhaps overlook something that causes those trailing bytes to still be hashed?
While working on porting aHash to https://github.com/inko-lang/inko I ran into the following:
aHash/src/fallback_hash.rs
Lines 170 to 192 in a9d649d
Specifically the following part appears problematic, at least at first sight:
aHash/src/fallback_hash.rs
Lines 180 to 184 in a9d649d
Imagine the input buffer is 18 bytes long. The following condition is then
true:aHash/src/fallback_hash.rs
Line 180 in a9d649d
Which means it runs this:
aHash/src/fallback_hash.rs
Lines 181 to 183 in a9d649d
The
read_u128will then return(16 bytes of data, 2 bytes of data). Because of thedata = restassignment, the next hit ofwhile data.len() > 16translates into2 > 16and thus the loop isn't run.Or more precisely, if the input size is not a multiple of 16 then up to 15 trailing bytes of input are not hashed.
I have a hard time imagining that this is in fact desired. Should that entire method not run in a loop to account for those trailing 15 bytes, or did I perhaps overlook something that causes those trailing bytes to still be hashed?