diff --git a/hermes/Cargo.toml b/hermes/Cargo.toml index 274882983..698d0712b 100644 --- a/hermes/Cargo.toml +++ b/hermes/Cargo.toml @@ -51,6 +51,7 @@ string_slice = "deny" unchecked_duration_subtraction = "deny" unreachable = "deny" missing_docs_in_private_items = "deny" +arithmetic_side_effects = "deny" [workspace.dependencies] # specific commit from the `catalyst` branch diff --git a/hermes/Earthfile b/hermes/Earthfile index 1f5eea940..dcc059f74 100644 --- a/hermes/Earthfile +++ b/hermes/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.03 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/hermes/bin/src/hdf5/file.rs b/hermes/bin/src/hdf5/file.rs index f3b29c74b..a234aa2a0 100644 --- a/hermes/bin/src/hdf5/file.rs +++ b/hermes/bin/src/hdf5/file.rs @@ -69,7 +69,7 @@ impl std::io::Read for File { let remaining_len = file_size.saturating_sub(self.pos); let reading_len = std::cmp::min(buf.len(), remaining_len); - let selection = hdf5::Selection::new(self.pos..self.pos + reading_len); + let selection = hdf5::Selection::new(self.pos..self.pos.saturating_add(reading_len)); let data = self .hdf5_ds @@ -96,7 +96,7 @@ impl std::io::Write for File { let new_shape = [file_size.saturating_add(increasing_len)]; self.hdf5_ds.resize(new_shape).map_err(map_to_io_error)?; - let selection = hdf5::Selection::new(self.pos..self.pos + buf.len()); + let selection = hdf5::Selection::new(self.pos..self.pos.saturating_add(buf.len())); self.hdf5_ds .write_slice(buf, selection) @@ -133,12 +133,10 @@ impl std::io::Seek for File { self.pos = n; Ok(self.pos.try_into().map_err(map_to_io_error)?) }, - None => { - Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "Invalid seek to a negative or overflowing position", - )) - }, + None => Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Invalid seek to a negative or overflowing position", + )), } } diff --git a/hermes/bin/src/runtime_extensions/hermes/cron/event.rs b/hermes/bin/src/runtime_extensions/hermes/cron/event.rs index aa2a6ca76..9d54b2215 100644 --- a/hermes/bin/src/runtime_extensions/hermes/cron/event.rs +++ b/hermes/bin/src/runtime_extensions/hermes/cron/event.rs @@ -18,7 +18,7 @@ impl Sub for CronDuration { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) + Self(self.0.saturating_sub(rhs.0)) } } @@ -241,22 +241,28 @@ mod tests { // every monday and the first day of January let cron: Cron = "0 0 1 1 7".parse().unwrap(); let times: Vec> = cron.clone().iter_from(datetime).take(5).collect(); - assert_eq!(times, vec![ - Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 1, 3, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 1, 10, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 1, 17, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 1, 24, 0, 0, 0).unwrap(), - ]); + assert_eq!( + times, + vec![ + Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 1, 3, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 1, 10, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 1, 17, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 1, 24, 0, 0, 0).unwrap(), + ] + ); let cron: Cron = "0 0 1 1,3,5,7,9,11 *".parse().unwrap(); let times: Vec> = cron.clone().iter_from(datetime).take(5).collect(); - assert_eq!(times, vec![ - Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 3, 1, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 5, 1, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 7, 1, 0, 0, 0).unwrap(), - Utc.with_ymd_and_hms(1970, 9, 1, 0, 0, 0).unwrap(), - ]); + assert_eq!( + times, + vec![ + Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 3, 1, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 5, 1, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 7, 1, 0, 0, 0).unwrap(), + Utc.with_ymd_and_hms(1970, 9, 1, 0, 0, 0).unwrap(), + ] + ); } } diff --git a/hermes/bin/src/runtime_extensions/hermes/cron/mod.rs b/hermes/bin/src/runtime_extensions/hermes/cron/mod.rs index f82a81348..53e46fde5 100644 --- a/hermes/bin/src/runtime_extensions/hermes/cron/mod.rs +++ b/hermes/bin/src/runtime_extensions/hermes/cron/mod.rs @@ -37,7 +37,9 @@ pub(crate) fn mkdelay_crontab( duration: Instant, tag: CronEventTag, ) -> wasmtime::Result { // Add the delay to the current time. - let delayed = Utc::now() + TimeDelta::nanoseconds(duration.try_into()?); + let delayed = Utc::now() + .checked_add_signed(TimeDelta::nanoseconds(duration.try_into()?)) + .ok_or(Error::InvalidTimestamp)?; let timestamp = delayed .timestamp_nanos_opt() .ok_or(Error::InvalidTimestamp)? @@ -238,26 +240,22 @@ impl CronComponent { fn merge(self, other: CronComponent) -> Option { match self { Self::All => Some(self), - Self::At(when) => { - match other { - Self::All => Some(Self::All), - Self::At(w) if w == when => Some(self), - Self::Range((a, b)) if (a..=b).contains(&when) => Some(other), - _ => None, - } + Self::At(when) => match other { + Self::All => Some(Self::All), + Self::At(w) if w == when => Some(self), + Self::Range((a, b)) if (a..=b).contains(&when) => Some(other), + _ => None, }, - Self::Range((first, last)) => { - match other { - Self::All => Some(Self::All), - Self::At(w) if (first..=last).contains(&w) => Some(self), - Self::Range((a, b)) - if ((first..=last).contains(&a) || (first..=last).contains(&b)) - || ((a..=b).contains(&first) || (a..=b).contains(&last)) => - { - Some(Self::Range((min(first, a), max(last, b)))) - }, - _ => None, - } + Self::Range((first, last)) => match other { + Self::All => Some(Self::All), + Self::At(w) if (first..=last).contains(&w) => Some(self), + Self::Range((a, b)) + if ((first..=last).contains(&a) || (first..=last).contains(&b)) + || ((a..=b).contains(&first) || (a..=b).contains(&last)) => + { + Some(Self::Range((min(first, a), max(last, b)))) + }, + _ => None, }, } } @@ -277,19 +275,15 @@ impl PartialEq for CronComponent { fn eq(&self, other: &Self) -> bool { match self { Self::All => matches!(other, Self::All), - Self::At(when) => { - match other { - Self::At(w) if w == when => true, - Self::Range((a, b)) if (a..=b).contains(&when) => true, - _ => false, - } + Self::At(when) => match other { + Self::At(w) if w == when => true, + Self::Range((a, b)) if (a..=b).contains(&when) => true, + _ => false, }, - Self::Range((first, last)) => { - match other { - Self::At(w) if first == w && last == w => true, - Self::Range((a, b)) if first == a && last == b => true, - _ => false, - } + Self::Range((first, last)) => match other { + Self::At(w) if first == w && last == w => true, + Self::Range((a, b)) if first == a && last == b => true, + _ => false, }, } } @@ -312,24 +306,18 @@ impl Eq for CronComponent {} impl Ord for CronComponent { fn cmp(&self, other: &Self) -> std::cmp::Ordering { match self { - Self::All => { - match other { - Self::All => std::cmp::Ordering::Equal, - _ => std::cmp::Ordering::Greater, - } + Self::All => match other { + Self::All => std::cmp::Ordering::Equal, + _ => std::cmp::Ordering::Greater, }, - Self::At(when) => { - match other { - Self::At(w) => when.cmp(w), - _ => std::cmp::Ordering::Less, - } + Self::At(when) => match other { + Self::At(w) => when.cmp(w), + _ => std::cmp::Ordering::Less, }, - Self::Range((first, last)) => { - match other { - Self::All => std::cmp::Ordering::Less, - Self::At(_) => std::cmp::Ordering::Greater, - Self::Range((start, end)) => first.cmp(start).then(last.cmp(end)), - } + Self::Range((first, last)) => match other { + Self::All => std::cmp::Ordering::Less, + Self::At(_) => std::cmp::Ordering::Greater, + Self::Range((start, end)) => first.cmp(start).then(last.cmp(end)), }, } } diff --git a/hermes/bin/src/runtime_extensions/hermes/cron/queue.rs b/hermes/bin/src/runtime_extensions/hermes/cron/queue.rs index 8f5493781..d24a250fc 100644 --- a/hermes/bin/src/runtime_extensions/hermes/cron/queue.rs +++ b/hermes/bin/src/runtime_extensions/hermes/cron/queue.rs @@ -162,6 +162,7 @@ impl CronEventQueue { } else { // If the timestamp is in the future, // update the waiting task. + #[allow(clippy::arithmetic_side_effects)] let sleep_duration = ts - trigger_time; self.update_waiting_task(ts, sleep_duration); // Since `ts` is in the future, we can break @@ -202,6 +203,7 @@ impl CronEventQueue { if !on_cron_event.last { // Re-schedule the event by calculating the next timestamp after now. if let Some(next_timestamp) = on_cron_event.tick_after(None) { + #[allow(clippy::arithmetic_side_effects)] let duration = next_timestamp - trigger_time; cron_queue_delay(app_name, duration.into(), on_cron_event.tag.tag)?; } @@ -507,10 +509,10 @@ mod tests { // sets the waiting_event assert!(!queue.waiting_event.is_empty()); // lists the event in the app queue - assert_eq!(queue.ls_events(&hermes_app_name, &None), vec![( - cron_entry_1().tag, - IS_LAST - )]); + assert_eq!( + queue.ls_events(&hermes_app_name, &None), + vec![(cron_entry_1().tag, IS_LAST)] + ); } #[test] @@ -530,10 +532,10 @@ mod tests { // which communicates with the static `CRON_INTERNAL_STATE`. assert!(queue.trigger().is_ok()); assert!(!queue.waiting_event.is_empty()); - assert_eq!(queue.ls_events(&hermes_app_name, &None), vec![( - cron_entry_2().tag, - IS_NOT_LAST - ),]); + assert_eq!( + queue.ls_events(&hermes_app_name, &None), + vec![(cron_entry_2().tag, IS_NOT_LAST),] + ); // wait for the waiting task to finish sleep(std::time::Duration::from_millis(500)); // Trigger manually diff --git a/hermes/bin/src/runtime_extensions/hermes/crypto/bip39.rs b/hermes/bin/src/runtime_extensions/hermes/crypto/bip39.rs index e31e28542..6339fd5d9 100644 --- a/hermes/bin/src/runtime_extensions/hermes/crypto/bip39.rs +++ b/hermes/bin/src/runtime_extensions/hermes/crypto/bip39.rs @@ -182,7 +182,7 @@ fn get_prefix_index_bits(prefix_list: Vec, language: Language) -> Result /// Note that if entropy bits is needed, multiply the `total_entropy_bytes` by 8. fn generate_entropy(word_count: usize) -> Result, Errno> { // Number of bytes entropy calculate from mnemonic word. - let total_entropy_bytes = word_count * 4 / 3; + let total_entropy_bytes = word_count.saturating_mul(4) / 3; // Maximum length of mnemonic is 24 words which is 32 bytes entropy. let mut total_entropy_bytes_max = [0u8; 32]; // Random number @@ -211,7 +211,7 @@ fn get_check_sum_bits(entropy_bits: &[u8], word_count: usize) -> Vec { // Retrieve the first `checksum_len` checksum bits from the hash result. let mut checksum_bits = Vec::new(); for i in 0..checksum_len { - checksum_bits.push(hash_result[0] >> (7 - i) & 1); + checksum_bits.push(hash_result[0] >> (7usize.saturating_sub(i)) & 1); } checksum_bits } @@ -223,11 +223,11 @@ fn get_word_indices(entropy_bits: &[u8], word_count: usize) -> Vec { // Separate entropy bits into 11 bits and convert to decimal. // This decimal will be used to get the word index. for i in 0..word_count { - let mut idx = 0; + let mut idx = 0u16; for j in 0..11 { - if let Some(value) = entropy_bits.get(i * 11 + j) { + if let Some(value) = entropy_bits.get(i.saturating_mul(11).saturating_add(j)) { if *value > 0 { - idx += 1 << (10 - j); + idx = idx.saturating_add(1 << (10usize.saturating_sub(j))); } } } @@ -257,7 +257,7 @@ fn decimal_to_binary_array(decimal: u16) -> [u8; 11] { while n > 0 { if let Some(value) = binary.get_mut(index) { let bit = n % 2; - index += 1; + index = index.saturating_add(1); *value = bit as u8; n /= 2; } @@ -268,7 +268,7 @@ fn decimal_to_binary_array(decimal: u16) -> [u8; 11] { if let Some(value) = binary.get_mut(index) { *value = 0; } - index += 1; + index = index.saturating_add(1); } binary.reverse(); binary @@ -278,10 +278,9 @@ fn decimal_to_binary_array(decimal: u16) -> [u8; 11] { fn bits_to_bytes(bits: &[u8]) -> Vec { bits.chunks(8) .map(|chunk| { - chunk - .iter() - .enumerate() - .fold(0, |acc, (i, &bit)| acc | ((bit) << (7 - i))) + chunk.iter().enumerate().fold(0, |acc, (i, &bit)| { + acc | ((bit) << (7usize.saturating_sub(i))) + }) }) .collect() } @@ -308,7 +307,7 @@ fn byte_to_bit(entropy: Vec, entropy_bits: &mut Vec, word_count: usize) for j in (0..8).rev() { // Should not exceed the word_count / 3 * 32 // which is number of entropy bits for the mnemonic word count. - if entropy_bits.len() >= word_count / 3 * 32 { + if entropy_bits.len() >= word_count.saturating_div(3).saturating_mul(32) { break; } entropy_bits.push((byte >> j) & 1); diff --git a/hermes/clippy.toml b/hermes/clippy.toml index 0358cdb50..caa289b27 100644 --- a/hermes/clippy.toml +++ b/hermes/clippy.toml @@ -1,2 +1,4 @@ allow-unwrap-in-tests = true allow-expect-in-tests = true +allow-panic-in-tests = true +arithmetic-side-effects-allowed = ["num_bigint::BigInt"] diff --git a/hermes/crates/cbork/Earthfile b/hermes/crates/cbork/Earthfile index e4772fb87..e56e8f7d7 100644 --- a/hermes/crates/cbork/Earthfile +++ b/hermes/crates/cbork/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.1.24 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/wasm/integration-test/cardano/Earthfile b/wasm/integration-test/cardano/Earthfile index 858e61618..39601970a 100644 --- a/wasm/integration-test/cardano/Earthfile +++ b/wasm/integration-test/cardano/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.03 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/wasm/integration-test/http_reply/Earthfile b/wasm/integration-test/http_reply/Earthfile index 9462f86f8..d46f1de59 100644 --- a/wasm/integration-test/http_reply/Earthfile +++ b/wasm/integration-test/http_reply/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.03 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/wasm/integration-test/ipfs/Earthfile b/wasm/integration-test/ipfs/Earthfile index 9477d535a..3c7ca9131 100644 --- a/wasm/integration-test/ipfs/Earthfile +++ b/wasm/integration-test/ipfs/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.03 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/wasm/integration-test/sqlite/Earthfile b/wasm/integration-test/sqlite/Earthfile index 3f2622716..5253c3d5f 100644 --- a/wasm/integration-test/sqlite/Earthfile +++ b/wasm/integration-test/sqlite/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.03 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/wasm/integration-test/wasi-filesystem/Earthfile b/wasm/integration-test/wasi-filesystem/Earthfile index e76909d30..6cfda98ec 100644 --- a/wasm/integration-test/wasi-filesystem/Earthfile +++ b/wasm/integration-test/wasi-filesystem/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.03 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/wasm/wasi-hermes-component-adapter/Cargo.toml b/wasm/wasi-hermes-component-adapter/Cargo.toml index 59cd7d9d3..95beafba0 100644 --- a/wasm/wasi-hermes-component-adapter/Cargo.toml +++ b/wasm/wasi-hermes-component-adapter/Cargo.toml @@ -50,6 +50,7 @@ string_slice = "deny" unchecked_duration_subtraction = "deny" unreachable = "deny" missing_docs_in_private_items = "deny" +arithmetic_side_effects = "deny" [workspace.dependencies] wit-bindgen = { version = "0.19.2", default-features = false } # Anything after 0.19.2 does not work. Do not bump version. diff --git a/wasm/wasi-hermes-component-adapter/Earthfile b/wasm/wasi-hermes-component-adapter/Earthfile index 65a8d75f9..e72389b8c 100644 --- a/wasm/wasi-hermes-component-adapter/Earthfile +++ b/wasm/wasi-hermes-component-adapter/Earthfile @@ -1,6 +1,6 @@ VERSION 0.8 -IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.03 AS rust-ci +IMPORT github.com/input-output-hk/catalyst-ci/earthly/rust:v3.2.28 AS rust-ci # Use when debugging cat-ci locally. # IMPORT ../../catalyst-ci/earthly/rust AS rust-ci diff --git a/wasm/wasi-hermes-component-adapter/build.rs b/wasm/wasi-hermes-component-adapter/build.rs index 96d644ccf..036c653c9 100644 --- a/wasm/wasi-hermes-component-adapter/build.rs +++ b/wasm/wasi-hermes-component-adapter/build.rs @@ -70,6 +70,7 @@ fn main() { /// The main trickiness here is getting the `reloc.CODE` and `linking` sections /// right. #[allow(clippy::too_many_lines)] +#[allow(clippy::expect_used)] fn build_raw_intrinsics() -> Vec { use wasm_encoder::{ ConstExpr, CustomSection, Encode, FunctionSection, GlobalSection, GlobalType, Instruction, @@ -135,12 +136,12 @@ fn build_raw_intrinsics() -> Vec { if instruction == global_set { Instruction::LocalGet(0).encode(&mut body); } - let global_offset = body.len() + 1; + let global_offset = body.len().checked_add(1).expect("Body length overflow"); // global.get $global ;; but with maximal encoding of $global - body.extend_from_slice(&[instruction, 0x80u8 + global, 0x80, 0x80, 0x80, 0x00]); + body.extend_from_slice(&[instruction, 0x80u8.checked_add(global).expect("instruction overflow"), 0x80, 0x80, 0x80, 0x00]); Instruction::End.encode(&mut body); body.len().encode(code); // length of the function - let offset = code.len() + global_offset; + let offset = code.len().checked_add(global_offset).expect("offset overflow"); code.extend_from_slice(&body); // the function itself offset }; @@ -246,6 +247,7 @@ fn build_raw_intrinsics() -> Vec { #[allow(clippy::unwrap_used)] #[allow(clippy::indexing_slicing)] #[allow(clippy::cast_possible_truncation)] +#[allow(clippy::expect_used)] fn build_archive(wasm: &[u8]) -> Vec { use object::{bytes_of, endian::BigEndian, U32Bytes}; @@ -305,8 +307,9 @@ fn build_archive(wasm: &[u8]) -> Vec { // and fill in the offset within the symbol table generated earlier. let member_offset = archive.len(); for (index, _) in syms.iter().enumerate() { - let index = index + 1; - archive[symtab_offset + (index * 4)..][..4].copy_from_slice(bytes_of(&U32Bytes::new( + let index = index.checked_add(1).expect("Index overflow"); + let offset = index.checked_mul(4).and_then(|v| v.checked_add(symtab_offset)).expect("Offset overflow"); + archive[offset..][..4].copy_from_slice(bytes_of(&U32Bytes::new( BigEndian, member_offset.try_into().unwrap(), ))); diff --git a/wasm/wasi-hermes-component-adapter/clippy.toml b/wasm/wasi-hermes-component-adapter/clippy.toml index 0358cdb50..caa289b27 100644 --- a/wasm/wasi-hermes-component-adapter/clippy.toml +++ b/wasm/wasi-hermes-component-adapter/clippy.toml @@ -1,2 +1,4 @@ allow-unwrap-in-tests = true allow-expect-in-tests = true +allow-panic-in-tests = true +arithmetic-side-effects-allowed = ["num_bigint::BigInt"] diff --git a/wasm/wasi-hermes-component-adapter/src/descriptors.rs b/wasm/wasi-hermes-component-adapter/src/descriptors.rs index 4271297f5..5df1d8dbd 100644 --- a/wasm/wasi-hermes-component-adapter/src/descriptors.rs +++ b/wasm/wasi-hermes-component-adapter/src/descriptors.rs @@ -252,7 +252,7 @@ impl Descriptors { return Err(wasi::ERRNO_NOMEM); } core::ptr::addr_of_mut!((*table)[len]).write(desc); - self.table_len.set(u16::try_from(len + 1).trapping_unwrap()); + self.table_len.set(u16::try_from(len.checked_add(1).trapping_unwrap()).trapping_unwrap()); Ok(Fd::from(u32::try_from(len).trapping_unwrap())) } } diff --git a/wasm/wasi-hermes-component-adapter/src/lib.rs b/wasm/wasi-hermes-component-adapter/src/lib.rs index 7e324a094..f69f5f2e0 100644 --- a/wasm/wasi-hermes-component-adapter/src/lib.rs +++ b/wasm/wasi-hermes-component-adapter/src/lib.rs @@ -215,10 +215,10 @@ impl BumpArena { #[allow(clippy::missing_docs_in_private_items)] fn alloc(&self, align: usize, size: usize) -> *mut u8 { let start = self.data.as_ptr() as usize; - let next = start + self.position.get(); + let next = start.checked_add(self.position.get()).unwrap(); let alloc = align_to(next, align); - let offset = alloc - start; - if offset + size > bump_arena_size() { + let offset = alloc.checked_sub(start).unwrap(); + if offset.checked_add(size).unwrap() > bump_arena_size() { unreachable!("out of memory"); } self.position.set(offset + size); @@ -891,7 +891,11 @@ pub unsafe extern "C" fn fd_pread( // Advance to the first non-empty buffer. while iovs_len != 0 && (*iovs_ptr).buf_len == 0 { iovs_ptr = iovs_ptr.add(1); - iovs_len -= 1; + if let Some(val) = iovs_len.checked_sub(1) { + iovs_len = val; + } else { + return ERRNO_INVAL; + } } if iovs_len == 0 { *nread = 0; @@ -1493,7 +1497,10 @@ pub unsafe extern "C" fn fd_write( if file.append { file.position.set(file.fd.stat()?.size); } else { - file.position.set(file.position.get() + nbytes as u64); + let Some(position) = file.position.get().checked_add(nbytes as u64) else { + return Err(ERRNO_INVAL); + }; + file.position.set(position); } } @@ -2557,16 +2564,16 @@ const fn bump_arena_size() -> usize { let mut start = PAGE_SIZE; // Remove big chunks of the struct for its various fields. - start -= size_of::(); + start = start.saturating_sub(size_of::()); #[cfg(not(feature = "proxy"))] { - start -= PATH_MAX; - start -= size_of::(); + start = start.saturating_sub(PATH_MAX); + start = start.saturating_sub(size_of::()); } // Remove miscellaneous metadata also stored in state. - let misc = if cfg!(feature = "proxy") { 7 } else { 14 }; - start -= misc * size_of::(); + let misc: usize = if cfg!(feature = "proxy") { 7 } else { 14 }; + start = start.saturating_sub(misc.saturating_mul(size_of::())); // Everything else is the `command_data` allocation. start