From 0244fe999c67c0cca459141900d7b79aad3c3bc1 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Fri, 23 Aug 2024 14:11:18 -0600 Subject: [PATCH] fix some array boundary issues in pretty print and testing Signed-off-by: Danno Ferrin --- .../besu/evmtool/CodeValidateSubCommand.java | 9 ++- .../besu/evmtool/PrettyPrintSubCommand.java | 8 +- .../hyperledger/besu/evm/code/EOFLayout.java | 74 +++++++++++++------ 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CodeValidateSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CodeValidateSubCommand.java index cb3ff9b8e70..d8be71cde13 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CodeValidateSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CodeValidateSubCommand.java @@ -155,9 +155,12 @@ private void checkCodeFromBufferedReader(final BufferedReader in) { public String considerCode(final String hexCode) { Bytes codeBytes; try { - codeBytes = - Bytes.fromHexString( - hexCode.replaceAll("(^|\n)#[^\n]*($|\n)", "").replaceAll("[^0-9A-Za-z]", "")); + String strippedString = + hexCode.replaceAll("(^|\n)#[^\n]*($|\n)", "").replaceAll("[^0-9A-Za-z]", ""); + if (Strings.isEmpty(strippedString)) { + return ""; + } + codeBytes = Bytes.fromHexString(strippedString); } catch (RuntimeException re) { return "err: hex string -" + re; } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/PrettyPrintSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/PrettyPrintSubCommand.java index aeff4a96b59..e24c24a21e9 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/PrettyPrintSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/PrettyPrintSubCommand.java @@ -89,7 +89,13 @@ public void run() { LogConfigurator.setLevel("", "OFF"); for (var hexCode : codeList) { - Bytes container = Bytes.fromHexString(hexCode); + Bytes container; + try { + container = Bytes.fromHexString(hexCode); + } catch (IllegalArgumentException e) { + parentCommand.out.println("Invalid hex string: " + e.getMessage()); + continue; + } if (container.get(0) != ((byte) 0xef) && container.get(1) != 0) { parentCommand.out.println( "Pretty printing of legacy EVM is not supported. Patches welcome!"); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java b/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java index d5abb05f868..8c221fe61d9 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java @@ -727,35 +727,59 @@ public void prettyPrint( OpcodeInfo ci = V1_OPCODES[byteCode[pc] & 0xff]; if (ci.opcode() == RelativeJumpVectorOperation.OPCODE) { - int tableSize = byteCode[pc + 1] & 0xff; - out.printf("%02x%02x", byteCode[pc], byteCode[pc + 1]); - for (int j = 0; j <= tableSize; j++) { - out.printf("%02x%02x", byteCode[pc + j * 2 + 2], byteCode[pc + j * 2 + 3]); - } - out.printf(" # [%d] %s(", pc, ci.name()); - for (int j = 0; j <= tableSize; j++) { - if (j != 0) { - out.print(','); + if (byteCode.length <= pc + 1) { + out.printf( + " %02x # [%d] %s()%n", byteCode[pc], pc, ci.name()); + pc++; + } else { + int tableSize = byteCode[pc + 1] & 0xff; + out.printf("%02x%02x", byteCode[pc], byteCode[pc + 1]); + int calculatedTableEnd = pc + tableSize * 2 + 4; + int lastTableEntry = Math.min(byteCode.length, calculatedTableEnd); + for (int j = pc + 2; j < lastTableEntry; j++) { + out.printf("%02x", byteCode[j]); + } + out.printf(" # [%d] %s(", pc, ci.name()); + for (int j = pc + 3; j < lastTableEntry; j += 2) { + // j indexes to the second byte of the word, to handle mid-word truncation + if (j != pc + 3) { + out.print(','); + } + int b0 = byteCode[j - 1]; // we want the sign extension, so no `& 0xff` + int b1 = byteCode[j] & 0xff; + out.print(b0 << 8 | b1); + } + if (byteCode.length < calculatedTableEnd) { + out.print(""); } - int b0 = byteCode[pc + j * 2 + 2]; // we want the sign extension, so no `& 0xff` - int b1 = byteCode[pc + j * 2 + 3] & 0xff; - out.print(b0 << 8 | b1); + pc += tableSize * 2 + 4; + out.print(")\n"); } - pc += tableSize * 2 + 4; - out.print(")\n"); } else if (ci.opcode() == RelativeJumpOperation.OPCODE || ci.opcode() == RelativeJumpIfOperation.OPCODE) { - int b0 = byteCode[pc + 1] & 0xff; - int b1 = byteCode[pc + 2] & 0xff; - short delta = (short) (b0 << 8 | b1); - out.printf("%02x%02x%02x # [%d] %s(%d)", byteCode[pc], b0, b1, pc, ci.name(), delta); + if (pc + 1 >= byteCode.length) { + out.printf(" %02x # [%d] %s()", byteCode[pc], pc, ci.name()); + } else if (pc + 2 >= byteCode.length) { + out.printf( + " %02x%02x # [%d] %s()", + byteCode[pc], byteCode[pc + 1], pc, ci.name()); + } else { + int b0 = byteCode[pc + 1] & 0xff; + int b1 = byteCode[pc + 2] & 0xff; + short delta = (short) (b0 << 8 | b1); + out.printf("%02x%02x%02x # [%d] %s(%d)", byteCode[pc], b0, b1, pc, ci.name(), delta); + } pc += 3; out.printf("%n"); } else if (ci.opcode() == ExchangeOperation.OPCODE) { - int imm = byteCode[pc + 1] & 0xff; - out.printf( - " %02x%02x # [%d] %s(%d, %d)", - byteCode[pc], imm, pc, ci.name(), imm >> 4, imm & 0x0F); + if (pc + 1 >= byteCode.length) { + out.printf(" %02x # [%d] %s()", byteCode[pc], pc, ci.name()); + } else { + int imm = byteCode[pc + 1] & 0xff; + out.printf( + " %02x%02x # [%d] %s(%d, %d)", + byteCode[pc], imm, pc, ci.name(), imm >> 4, imm & 0x0F); + } pc += 2; out.printf("%n"); } else { @@ -771,7 +795,11 @@ public void prettyPrint( } out.printf(" # [%d] %s", pc, ci.name()); if (advance == 2) { - out.printf("(%d)", byteCode[pc + 1] & 0xff); + if (byteCode.length <= pc + 1) { + out.print("()"); + } else { + out.printf("(%d)", byteCode[pc + 1] & 0xff); + } } else if (advance > 2) { out.print("(0x"); for (int j = 1; j < advance && (pc + j) < byteCode.length; j++) {