CVE-2022-36008: Integer Overflow or Wraparound (CWE-190)
value: Frontier is Substrate's Ethereum compatibility layer. A security issue was discovered affecting parsing of the RPC result of the exit reason in case of EVM reversion. In release build, this would cause the exit reason being incorrectly parsed and returned by RPC. In debug build, this would cause an overflow panic. No action is needed unless you have a bridge node that needs to distinguish different reversion exit reasons and you used RPC for this. There are currently no known workarounds.
CWE description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
CVSS v3 base score: 6.5
Published: 2022-08-19T21:15Z
Repository: https://github.com/paritytech/frontier
Language: Rust
Files changed: client/rpc/src/eth/execute.rs
Commit date: 2022-08-15 15:01:03 +0200
Commit message: Fix length checking overflow in EVM revert reason parsing (#820)

* Fix length checking overflow in EVM revert reason parsing

* Remove unused debug_assert
Diff: diff --git a/client/rpc/src/eth/execute.rs b/client/rpc/src/eth/execute.rs
index d6ff4412..46190de6 100644
--- a/client/rpc/src/eth/execute.rs
+++ b/client/rpc/src/eth/execute.rs
@@ -29,10 +29,11 @@ use sp_api::{ApiExt, ProvideRuntimeApi};
 use sp_block_builder::BlockBuilder as BlockBuilderApi;
 use sp_blockchain::{BlockStatus, HeaderBackend};
 use sp_runtime::{
 	generic::BlockId,
 	traits::{BlakeTwo256, Block as BlockT},
+	SaturatedConversion,
 };
 
 use fc_rpc_core::types::*;
 use fp_rpc::EthereumRuntimeRPCApi;
 
@@ -686,17 +687,23 @@ pub fn error_on_execution_failure(reason: &ExitReason, data: &[u8]) -> Result<()
 				format!("evm error: {:?}", e),
 				&[],
 			))
 		}
 		ExitReason::Revert(_) => {
+			const LEN_START: usize = 36;
+			const MESSAGE_START: usize = 68;
+
 			let mut message = "VM Exception while processing transaction: revert".to_string();
 			// A minimum size of error function selector (4) + offset (32) + string length (32)
 			// should contain a utf-8 encoded revert reason.
-			if data.len() > 68 {
-				let message_len = data[36..68].iter().sum::<u8>();
-				if data.len() >= 68 + message_len as usize {
-					let body: &[u8] = &data[68..68 + message_len as usize];
+			if data.len() > MESSAGE_START {
+				let message_len =
+					U256::from(&data[LEN_START..MESSAGE_START]).saturated_into::<usize>();
+				let message_end = MESSAGE_START.saturating_add(message_len);
+
+				if data.len() >= message_end {
+					let body: &[u8] = &data[MESSAGE_START..message_end];
 					if let Ok(reason) = std::str::from_utf8(body) {
 						message = format!("{} {}", message, reason);
 					}
 				}
 			}

Vulnerable code: 			if data.len() > 68 {
				let message_len = data[36..68].iter().sum::<u8>();
				if data.len() >= 68 + message_len as usize {
					let body: &[u8] = &data[68..68 + message_len as usize];
Fixed code: 	SaturatedConversion,
			const LEN_START: usize = 36;
			const MESSAGE_START: usize = 68;

			if data.len() > MESSAGE_START {
				let message_len =
					U256::from(&data[LEN_START..MESSAGE_START]).saturated_into::<usize>();
				let message_end = MESSAGE_START.saturating_add(message_len);

				if data.len() >= message_end {
					let body: &[u8] = &data[MESSAGE_START..message_end];