diff --git a/crypto/txscript/src/data_stack.rs b/crypto/txscript/src/data_stack.rs index 0ccd47627..1270cf0df 100644 --- a/crypto/txscript/src/data_stack.rs +++ b/crypto/txscript/src/data_stack.rs @@ -22,7 +22,7 @@ pub(crate) trait DataStack { Vec: OpcodeData; fn pop_raw(&mut self) -> Result<[Vec; SIZE], TxScriptError>; fn peek_raw(&self) -> Result<[Vec; SIZE], TxScriptError>; - fn push_item(&mut self, item: T) + fn push_item(&mut self, item: T) -> Result<(), TxScriptError> where Vec: OpcodeData; fn drop_items(&mut self) -> Result<(), TxScriptError>; @@ -269,11 +269,16 @@ impl DataStack for Stack { } #[inline] - fn push_item(&mut self, item: T) + fn push_item(&mut self, item: T) -> Result<(), TxScriptError> where Vec: OpcodeData, { - Vec::push(self, OpcodeData::serialize(&item)); + let v: Vec = OpcodeData::serialize(&item); + if v.len() > 8 { + return Err(TxScriptError::NumberTooBig("Binary representation of {item:?} is longer than 8 bytes".to_string())); + } + Vec::push(self, v); + Ok(()) } #[inline] diff --git a/crypto/txscript/src/lib.rs b/crypto/txscript/src/lib.rs index f2fb7048b..c4821a2f0 100644 --- a/crypto/txscript/src/lib.rs +++ b/crypto/txscript/src/lib.rs @@ -461,7 +461,7 @@ impl<'a, T: VerifiableTransaction, Reused: SigHashReusedValues> TxScriptEngine<' return Err(TxScriptError::NullFail); } - self.dstack.push_item(!failed); + self.dstack.push_item(!failed)?; Ok(()) } diff --git a/crypto/txscript/src/opcodes/mod.rs b/crypto/txscript/src/opcodes/mod.rs index 3da4e8790..84393fd12 100644 --- a/crypto/txscript/src/opcodes/mod.rs +++ b/crypto/txscript/src/opcodes/mod.rs @@ -212,7 +212,10 @@ fn push_number( number: i64, vm: &mut TxScriptEngine, ) -> OpCodeResult { - vm.dstack.push_item(number); + if number == i64::MIN { + return Err(TxScriptError::NumberTooBig(format!("Binary representation of {number} exceeds 8 bytes limit"))); + } + vm.dstack.push_item(number)?; Ok(()) } @@ -224,13 +227,13 @@ macro_rules! numeric_op { if $vm.kip10_enabled { let $pattern: [Kip10I64; $count] = $vm.dstack.pop_items()?; let r = $block; - $vm.dstack.push_item(r); + $vm.dstack.push_item(r)?; Ok(()) } else { let $pattern: [i64; $count] = $vm.dstack.pop_items()?; #[allow(clippy::useless_conversion)] let r = $block; - $vm.dstack.push_item(r); + $vm.dstack.push_item(r)?; Ok(()) } }; @@ -543,7 +546,7 @@ opcode_list! { opcode OpSize<0x82, 1>(self, vm) { match vm.dstack.last() { Some(last) => { - vm.dstack.push_item(i64::try_from(last.len()).map_err(|e| TxScriptError::NumberTooBig(e.to_string()))?); + vm.dstack.push_item(i64::try_from(last.len()).map_err(|e| TxScriptError::NumberTooBig(e.to_string()))?)?; Ok(()) }, None => Err(TxScriptError::InvalidStackOperation(1, 0)) @@ -721,7 +724,7 @@ opcode_list! { let hash_type = SigHashType::from_u8(typ).map_err(|e| TxScriptError::InvalidSigHashType(typ))?; match vm.check_ecdsa_signature(hash_type, key.as_slice(), sig.as_slice()) { Ok(valid) => { - vm.dstack.push_item(valid); + vm.dstack.push_item(valid)?; Ok(()) }, Err(e) => { @@ -730,7 +733,7 @@ opcode_list! { } } None => { - vm.dstack.push_item(false); + vm.dstack.push_item(false)?; Ok(()) } } @@ -744,7 +747,7 @@ opcode_list! { let hash_type = SigHashType::from_u8(typ).map_err(|e| TxScriptError::InvalidSigHashType(typ))?; match vm.check_schnorr_signature(hash_type, key.as_slice(), sig.as_slice()) { Ok(valid) => { - vm.dstack.push_item(valid); + vm.dstack.push_item(valid)?; Ok(()) }, Err(e) => { @@ -753,7 +756,7 @@ opcode_list! { } } None => { - vm.dstack.push_item(false); + vm.dstack.push_item(false)?; Ok(()) } } @@ -3097,7 +3100,7 @@ mod test { assert!(matches!(op_input_idx.execute(&mut vm), Err(TxScriptError::InvalidOpcode(_)))); } else { let mut expected = vm.dstack.clone(); - expected.push_item(current_idx as i64); + expected.push_item(current_idx as i64).unwrap(); op_input_idx.execute(&mut vm).unwrap(); assert_eq!(vm.dstack, expected); vm.dstack.clear(); diff --git a/crypto/txscript/test-data/script_tests-kip10.json b/crypto/txscript/test-data/script_tests-kip10.json index c0d1c5e69..22fafe6c9 100644 --- a/crypto/txscript/test-data/script_tests-kip10.json +++ b/crypto/txscript/test-data/script_tests-kip10.json @@ -4408,6 +4408,13 @@ "UNKNOWN_ERROR", "We cannot do BOOLAND on 9-byte integers" ], + [ + "-9223372036854775807", + "1SUB", + "", + "UNKNOWN_ERROR", + "Interpret 9 byte integer as bool" + ], [ "1", "1 ENDIF",