From 5f46aa62ea33dc8676dee5df4c8aa61dabf4f1e6 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Sun, 12 Mar 2023 10:45:47 +0100 Subject: [PATCH 1/3] Check jumps --- src/Neo/SmartContract/Helper.cs | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index 73b19f9616..552ade772b 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -78,6 +78,69 @@ public static void Check(byte[] script, ContractAbi abi) /// Note: The passed to this method should be constructed with strict mode. public static void Check(this Script script, ContractAbi abi) { + if (abi is null) throw new ArgumentNullException(nameof(abi)); + + Dictionary instructions = new(); + for (int ip = 0; ip < script.Length;) + { + Instruction instruction = script.GetInstruction(ip); + instructions.Add(ip, instruction); + ip += instruction.Size; + } + foreach (var (ip, instruction) in instructions) + { + switch (instruction.OpCode) + { + case OpCode.JMP: + case OpCode.JMPIF: + case OpCode.JMPIFNOT: + case OpCode.JMPEQ: + case OpCode.JMPNE: + case OpCode.JMPGT: + case OpCode.JMPGE: + case OpCode.JMPLT: + case OpCode.JMPLE: + case OpCode.CALL: + case OpCode.ENDTRY: + if (!instructions.ContainsKey(checked(ip + instruction.TokenI8))) + throw new IndexOutOfRangeException(); + break; + case OpCode.PUSHA: + case OpCode.JMP_L: + case OpCode.JMPIF_L: + case OpCode.JMPIFNOT_L: + case OpCode.JMPEQ_L: + case OpCode.JMPNE_L: + case OpCode.JMPGT_L: + case OpCode.JMPGE_L: + case OpCode.JMPLT_L: + case OpCode.JMPLE_L: + case OpCode.CALL_L: + case OpCode.ENDTRY_L: + if (!instructions.ContainsKey(checked(ip + instruction.TokenI32))) + throw new IndexOutOfRangeException(); + break; + case OpCode.TRY: + if (!instructions.ContainsKey(checked(ip + instruction.TokenI8)) || + !instructions.ContainsKey(checked(ip + instruction.TokenI8_1))) + throw new IndexOutOfRangeException(); + break; + case OpCode.TRY_L: + if (!instructions.ContainsKey(checked(ip + instruction.TokenI32)) || + !instructions.ContainsKey(checked(ip + instruction.TokenI32_1))) + throw new IndexOutOfRangeException(); + break; + case OpCode.NEWARRAY_T: + case OpCode.ISTYPE: + case OpCode.CONVERT: + StackItemType type = (StackItemType)instruction.TokenU8; + if (!Enum.IsDefined(typeof(StackItemType), type) || + instruction.OpCode != OpCode.NEWARRAY_T && type == StackItemType.Any) + throw new IndexOutOfRangeException(); + break; + } + } + foreach (ContractMethodDescriptor method in abi.Methods) script.GetInstruction(method.Offset); abi.GetMethod(string.Empty, 0); // Trigger the construction of ContractAbi.methodDictionary to check the uniqueness of the method names. From 2e76470007f3d3c2ff3c0dbc4288e1b753c449ff Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Mar 2023 11:24:54 +0100 Subject: [PATCH 2/3] Use strict mode --- src/Neo/SmartContract/Native/ContractManagement.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 875dcf1f50..8cc6b54588 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -231,7 +231,7 @@ private async ContractTask Deploy(ApplicationEngine engine, byte[ NefFile nef = nefFile.AsSerializable(); ContractManifest parsedManifest = ContractManifest.Parse(manifest); - Helper.Check(nef.Script, parsedManifest.Abi); + Helper.Check(new VM.Script(nef.Script, true), parsedManifest.Abi); UInt160 hash = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name); if (Policy.IsBlocked(engine.Snapshot, hash)) @@ -295,7 +295,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}"); contract.Manifest = manifest_new; } - Helper.Check(contract.Nef.Script, contract.Manifest.Abi); + Helper.Check(new VM.Script(contract.Nef.Script, true), contract.Manifest.Abi); contract.UpdateCounter++; // Increase update counter return OnDeploy(engine, contract, data, true); } From 4eef3c89caef19f6146ce15e8dbaa84265518024 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Mar 2023 11:26:11 +0100 Subject: [PATCH 3/3] Revert changes --- src/Neo/SmartContract/Helper.cs | 63 --------------------------------- 1 file changed, 63 deletions(-) diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index 552ade772b..73b19f9616 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -78,69 +78,6 @@ public static void Check(byte[] script, ContractAbi abi) /// Note: The passed to this method should be constructed with strict mode. public static void Check(this Script script, ContractAbi abi) { - if (abi is null) throw new ArgumentNullException(nameof(abi)); - - Dictionary instructions = new(); - for (int ip = 0; ip < script.Length;) - { - Instruction instruction = script.GetInstruction(ip); - instructions.Add(ip, instruction); - ip += instruction.Size; - } - foreach (var (ip, instruction) in instructions) - { - switch (instruction.OpCode) - { - case OpCode.JMP: - case OpCode.JMPIF: - case OpCode.JMPIFNOT: - case OpCode.JMPEQ: - case OpCode.JMPNE: - case OpCode.JMPGT: - case OpCode.JMPGE: - case OpCode.JMPLT: - case OpCode.JMPLE: - case OpCode.CALL: - case OpCode.ENDTRY: - if (!instructions.ContainsKey(checked(ip + instruction.TokenI8))) - throw new IndexOutOfRangeException(); - break; - case OpCode.PUSHA: - case OpCode.JMP_L: - case OpCode.JMPIF_L: - case OpCode.JMPIFNOT_L: - case OpCode.JMPEQ_L: - case OpCode.JMPNE_L: - case OpCode.JMPGT_L: - case OpCode.JMPGE_L: - case OpCode.JMPLT_L: - case OpCode.JMPLE_L: - case OpCode.CALL_L: - case OpCode.ENDTRY_L: - if (!instructions.ContainsKey(checked(ip + instruction.TokenI32))) - throw new IndexOutOfRangeException(); - break; - case OpCode.TRY: - if (!instructions.ContainsKey(checked(ip + instruction.TokenI8)) || - !instructions.ContainsKey(checked(ip + instruction.TokenI8_1))) - throw new IndexOutOfRangeException(); - break; - case OpCode.TRY_L: - if (!instructions.ContainsKey(checked(ip + instruction.TokenI32)) || - !instructions.ContainsKey(checked(ip + instruction.TokenI32_1))) - throw new IndexOutOfRangeException(); - break; - case OpCode.NEWARRAY_T: - case OpCode.ISTYPE: - case OpCode.CONVERT: - StackItemType type = (StackItemType)instruction.TokenU8; - if (!Enum.IsDefined(typeof(StackItemType), type) || - instruction.OpCode != OpCode.NEWARRAY_T && type == StackItemType.Any) - throw new IndexOutOfRangeException(); - break; - } - } - foreach (ContractMethodDescriptor method in abi.Methods) script.GetInstruction(method.Offset); abi.GetMethod(string.Empty, 0); // Trigger the construction of ContractAbi.methodDictionary to check the uniqueness of the method names.