diff --git a/electrum/transaction.py b/electrum/transaction.py index b5f6e79ba..cad9b2249 100644 --- a/electrum/transaction.py +++ b/electrum/transaction.py @@ -597,7 +597,6 @@ class BCDataStream(object): def script_GetOp(_bytes : bytes): - _bytes_len = len(_bytes) i = 0 while i < len(_bytes): vch = None @@ -618,10 +617,9 @@ def script_GetOp(_bytes : bytes): try: (nSize,) = struct.unpack_from(' _bytes_len - i: - raise MalformedBitcoinScript(f"Push of data element that is larger than remaining data: {nSize} vs {_bytes_len - i}") - + if i + nSize > len(_bytes): + raise MalformedBitcoinScript( + f"Push of data element that is larger than remaining data: {nSize} vs {len(_bytes) - i}") vch = _bytes[i:i + nSize] i += nSize diff --git a/tests/test_transaction.py b/tests/test_transaction.py index d4a10f1a4..6757d824e 100644 --- a/tests/test_transaction.py +++ b/tests/test_transaction.py @@ -8,7 +8,8 @@ from electrum import transaction, bitcoin from electrum.transaction import (convert_raw_tx_to_hex, tx_from_any, Transaction, PartialTransaction, TxOutpoint, PartialTxInput, PartialTxOutput, Sighash, match_script_against_template, - SCRIPTPUBKEY_TEMPLATE_ANYSEGWIT, TxOutput) + SCRIPTPUBKEY_TEMPLATE_ANYSEGWIT, TxOutput, script_GetOp, + MalformedBitcoinScript) from electrum.util import bfh from electrum.bitcoin import (deserialize_privkey, opcodes, construct_script, construct_witness) @@ -91,6 +92,16 @@ class TestTransaction(ElectrumTestCase): script = construct_script([opcodes.OP_0, bytes(50)]) self.assertFalse(match_script_against_template(script, SCRIPTPUBKEY_TEMPLATE_ANYSEGWIT)) + def test_script_GetOp(self): + # TODO add more test cases for script_GetOp + # cases from https://github.com/bitcoinj/bitcoinj/blob/09defa626648687f8bd6ea7d197818249eebd3c8/core/src/test/resources/org/bitcoinj/script/script_tests.json#L721-L723 + with self.assertRaises(MalformedBitcoinScript): + [x for x in script_GetOp(bfh("4c01"))] # PUSHDATA1 with not enough bytes + with self.assertRaises(MalformedBitcoinScript): + [x for x in script_GetOp(bfh("4d0200ff"))] # PUSHDATA2 with not enough bytes + with self.assertRaises(MalformedBitcoinScript): + [x for x in script_GetOp(bfh("4e03000000ffff"))] # PUSHDATA4 with not enough bytes + def test_tx_update_signatures(self): tx = tx_from_any("cHNidP8BAFUBAAAAASpcmpT83pj1WBzQAWLGChOTbOt1OJ6mW/OGM7Qk60AxAAAAAAD/////AUBCDwAAAAAAGXapFCMKw3g0BzpCFG8R74QUrpKf6q/DiKwAAAAAAAAA") pubkey = bfh('02e61d176da16edd1d258a200ad9759ef63adf8e14cd97f53227bae35cdb84d2f6')