Fix CodeBytes: invalidPositions out of bound crash (#2523)
This commit is contained in:
parent
3a7f025fd9
commit
0cc730dd05
|
@ -64,7 +64,7 @@ func isValidOpcode*(c: CodeBytesRef, position: int): bool =
|
||||||
var opcode = Op(c.bytes[i])
|
var opcode = Op(c.bytes[i])
|
||||||
if opcode >= Op.Push1 and opcode <= Op.Push32:
|
if opcode >= Op.Push1 and opcode <= Op.Push32:
|
||||||
var leftBound = (i + 1)
|
var leftBound = (i + 1)
|
||||||
var rightBound = leftBound + (opcode.int - 95)
|
var rightBound = min(leftBound + (opcode.int - 95), c.bytes.len)
|
||||||
for z in leftBound ..< rightBound:
|
for z in leftBound ..< rightBound:
|
||||||
let (bpos, bbit) = bitpos(z)
|
let (bpos, bbit) = bitpos(z)
|
||||||
c.invalidPositions[bpos] = c.invalidPositions[bpos] or bbit
|
c.invalidPositions[bpos] = c.invalidPositions[bpos] or bbit
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, strutils], chronicles, eth/common, ./interpreter/op_codes, ./code_bytes
|
chronicles,
|
||||||
|
eth/common,
|
||||||
|
stew/byteutils,
|
||||||
|
./interpreter/op_codes,
|
||||||
|
./code_bytes
|
||||||
|
|
||||||
export code_bytes
|
export code_bytes
|
||||||
|
|
||||||
|
@ -80,24 +84,23 @@ func isValidOpcode*(c: CodeStream, position: int): bool =
|
||||||
func bytes*(c: CodeStream): lent seq[byte] =
|
func bytes*(c: CodeStream): lent seq[byte] =
|
||||||
c.code.bytes()
|
c.code.bytes()
|
||||||
|
|
||||||
|
func atEnd*(c: CodeStream): bool =
|
||||||
|
c.pc >= c.code.bytes.len
|
||||||
|
|
||||||
proc decompile*(original: CodeStream): seq[(int, Op, string)] =
|
proc decompile*(original: CodeStream): seq[(int, Op, string)] =
|
||||||
# behave as https://etherscan.io/opcode-tool
|
# behave as https://etherscan.io/opcode-tool
|
||||||
var c = CodeStream.init(original.bytes)
|
var c = CodeStream.init(original.bytes)
|
||||||
while true:
|
while not c.atEnd:
|
||||||
var op = c.next
|
var op = c.next
|
||||||
if op >= Push1 and op <= Push32:
|
if op >= Push1 and op <= Push32:
|
||||||
result.add(
|
result.add(
|
||||||
(
|
(
|
||||||
c.pc - 1,
|
c.pc - 1,
|
||||||
op,
|
op,
|
||||||
"0x" & c.read(op.int - 95).mapIt($(it.BiggestInt.toHex(2))).join(""),
|
"0x" & c.read(op.int - 95).toHex,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif op != Op.Stop:
|
elif op != Op.Stop:
|
||||||
result.add((c.pc - 1, op, ""))
|
result.add((c.pc - 1, op, ""))
|
||||||
else:
|
else:
|
||||||
result.add((-1, Op.Stop, ""))
|
result.add((-1, Op.Stop, ""))
|
||||||
break
|
|
||||||
|
|
||||||
func atEnd*(c: CodeStream): bool =
|
|
||||||
c.pc >= c.code.bytes.len
|
|
||||||
|
|
|
@ -953,5 +953,14 @@ proc opMemoryMain*() =
|
||||||
success: false
|
success: false
|
||||||
fork: Cancun
|
fork: Cancun
|
||||||
|
|
||||||
|
assembler:
|
||||||
|
title: "Code bytes: invalidPositions out of bound crash issue #2522"
|
||||||
|
code:
|
||||||
|
Push1 "0x01" # 0: ok to jump
|
||||||
|
Push1 "0x06" # 2: jump to pc 6
|
||||||
|
JumpI # 4
|
||||||
|
"0x695b00" # 5: PUSH10 First byte is jumpDestOp but operand is too short
|
||||||
|
success: false
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
opMemoryMain()
|
opMemoryMain()
|
||||||
|
|
|
@ -67,9 +67,8 @@ proc toBytes(x: string): seq[byte] =
|
||||||
method getAncestorHash(vmState: TestVMState; blockNumber: BlockNumber): Hash256 =
|
method getAncestorHash(vmState: TestVMState; blockNumber: BlockNumber): Hash256 =
|
||||||
keccakHash(toBytes($blockNumber))
|
keccakHash(toBytes($blockNumber))
|
||||||
|
|
||||||
proc verifyResult(ctx: var StateContext, vmState: BaseVMState) =
|
proc verifyResult(ctx: var StateContext, vmState: BaseVMState, obtainedHash: Hash256) =
|
||||||
ctx.error = ""
|
ctx.error = ""
|
||||||
let obtainedHash = vmState.readOnlyStateDB.rootHash
|
|
||||||
if obtainedHash != ctx.expectedHash:
|
if obtainedHash != ctx.expectedHash:
|
||||||
ctx.error = "post state root mismatch: got $1, want $2" %
|
ctx.error = "post state root mismatch: got $1, want $2" %
|
||||||
[($obtainedHash).toLowerAscii, $ctx.expectedHash]
|
[($obtainedHash).toLowerAscii, $ctx.expectedHash]
|
||||||
|
@ -99,31 +98,9 @@ proc writeResultToStdout(stateRes: seq[StateResult]) =
|
||||||
stdout.write(n.pretty)
|
stdout.write(n.pretty)
|
||||||
stdout.write("\n")
|
stdout.write("\n")
|
||||||
|
|
||||||
when false:
|
proc writeRootHashToStderr(stateRoot: Hash256) =
|
||||||
proc dumpAccounts(db: LedgerRef): Table[EthAddress, DumpAccount] =
|
|
||||||
for accAddr in db.addresses():
|
|
||||||
let acc = DumpAccount(
|
|
||||||
balance : db.getBalance(accAddr),
|
|
||||||
nonce : db.getNonce(accAddr),
|
|
||||||
root : db.getStorageRoot(accAddr),
|
|
||||||
codeHash: db.getCodeHash(accAddr),
|
|
||||||
code : db.getCode(accAddr),
|
|
||||||
key : keccakHash(accAddr)
|
|
||||||
)
|
|
||||||
for k, v in db.storage(accAddr):
|
|
||||||
acc.storage[k] = v
|
|
||||||
result[accAddr] = acc
|
|
||||||
|
|
||||||
|
|
||||||
proc dumpState(vmState: BaseVMState): StateDump =
|
|
||||||
StateDump(
|
|
||||||
root: vmState.readOnlyStateDB.rootHash,
|
|
||||||
accounts: dumpAccounts(vmState.stateDB)
|
|
||||||
)
|
|
||||||
|
|
||||||
proc writeRootHashToStderr(vmState: BaseVMState) =
|
|
||||||
let stateRoot = %{
|
let stateRoot = %{
|
||||||
"stateRoot": %(vmState.readOnlyStateDB.rootHash)
|
"stateRoot": %(stateRoot)
|
||||||
}
|
}
|
||||||
stderr.writeLine($stateRoot)
|
stderr.writeLine($stateRoot)
|
||||||
|
|
||||||
|
@ -159,18 +136,19 @@ proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateR
|
||||||
db.persist(clearEmptyAccount = false) # settle accounts storage
|
db.persist(clearEmptyAccount = false) # settle accounts storage
|
||||||
|
|
||||||
defer:
|
defer:
|
||||||
ctx.verifyResult(vmState)
|
let stateRoot = vmState.readOnlyStateDB.rootHash
|
||||||
|
ctx.verifyResult(vmState, stateRoot)
|
||||||
result = StateResult(
|
result = StateResult(
|
||||||
name : ctx.name,
|
name : ctx.name,
|
||||||
pass : ctx.error.len == 0,
|
pass : ctx.error.len == 0,
|
||||||
root : vmState.readOnlyStateDB.rootHash,
|
root : stateRoot,
|
||||||
fork : ctx.forkStr,
|
fork : ctx.forkStr,
|
||||||
error: ctx.error
|
error: ctx.error
|
||||||
)
|
)
|
||||||
if conf.dumpEnabled:
|
if conf.dumpEnabled:
|
||||||
result.state = dumpState(vmState.stateDB)
|
result.state = dumpState(vmState.stateDB)
|
||||||
if conf.jsonEnabled:
|
if conf.jsonEnabled:
|
||||||
writeRootHashToStderr(vmState)
|
writeRootHashToStderr(stateRoot)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
let rc = vmState.processTransaction(
|
let rc = vmState.processTransaction(
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"01400578-mixed-11": {
|
||||||
|
"env": {
|
||||||
|
"currentCoinbase": "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||||
|
"currentDifficulty": "0x200000",
|
||||||
|
"currentRandom": "0x0000000000000000000000000000000000000000000000000000000000200000",
|
||||||
|
"currentGasLimit": "0x26e1f476fe1e22",
|
||||||
|
"currentNumber": "0x1",
|
||||||
|
"currentTimestamp": "0x3e8",
|
||||||
|
"previousHash": "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d",
|
||||||
|
"currentBaseFee": "0x10"
|
||||||
|
},
|
||||||
|
"pre": {
|
||||||
|
"0x00000000000000000000000000000000000000f1": {
|
||||||
|
"code": "0x605e607f6084600c60f760da603f4257527a7f995050406839323e027077853c6a3330146282387532923e0993618743475b10018e09179e66407c48198ef5349e8e898183740080781d5b308a1189473617771660588c96639c4610643d17741b117734429e81198f5307737981fda26448436303577d312020015a0a9e035a75865576869d895774736dfd656e518e895643346b4392325697483f39637c699d93868b32035562419459550b5a416b647510455134fe47823a085369737f6d6e88387e8d055686771478fd3877351868a082656199857940605411351a09050b123b37517c9e74504376848814727c04483f361b6a61396c7a7f010b72338e358b5b348b8542118d148d7266f21578a033475a523e717f8d31a3fda01257a1898d6f82401b583b514883368c5b62845044107c5a6e637f09868a818564203f14086e6085168832906d0896793c113e973d3348020594718385533082029a8b65026e4858391a901a557c5783081aa358f339147c85029a3240f30b77029d91f13e6f179c31784704606f07524486159452060656ff4515500a7d8a8d3f98768a3e68053b91628d1d38036907587d585b9c32601c6d3b40076efd39168b931c151b6e73041b930a7640764568794030070881548b86101000ff30567884045504468a1d6e2016098e2008141877831c3b3d7556815983917a061242186c98739a087d01603ffe03689d805b064492a11212039b40146d67200902fd44088f94867a916a008079a4366e31601890f3153f6c0a611d023177783e19f53f408509885064a159046388863e82173a599c095b9864449456305030518ea341691ba37f7442f1038ef206578a3d860b67959d18879e8d8418596e70899b016c817310ff42307c3006788c3f32546f6e63364320593e3c356814677492117d653b61933c8b45a06677105b0a541c99115856983774037c801553a0806f423b508f1c3368716809557c3676105143617e6207606f07897b634833203c17609f7467823042763f1431005267705417836c8f951b458b3d50806b806d141530830611a372511575636260613082ff185180597a8054f346811201733b771d898f07745734816bfd1b41411d0964575b110405204472075b6d5b7955a11084f0a460849e3b371c81695b9a3e30607866f19b097d5954651a595257446010840402578643351a15778c84f35231090b9544f035155242593d7e04a3327462417c9d7271849f64643843156d04f5811c620987350b50596c7f947b38778f3d431482856f97809d068d46658d31468b887e350a7a7815966984437432343a6a6803080645f272581690013e7d1132734167761807711dfa8d9d563c388b8246684174f487404170369d44387e47925b886f3c380b131d10fe1af06e4873123634a2007d93656b",
|
||||||
|
"storage": {},
|
||||||
|
"balance": "0x0",
|
||||||
|
"nonce": "0x0"
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"code": "0x",
|
||||||
|
"storage": {},
|
||||||
|
"balance": "0xffffffffff",
|
||||||
|
"nonce": "0x0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transaction": {
|
||||||
|
"gasPrice": "0x10",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"to": "0x00000000000000000000000000000000000000f1",
|
||||||
|
"data": [
|
||||||
|
"0xa789e12ba04bb2"
|
||||||
|
],
|
||||||
|
"gasLimit": [
|
||||||
|
"0x5299"
|
||||||
|
],
|
||||||
|
"value": [
|
||||||
|
"0x"
|
||||||
|
],
|
||||||
|
"sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||||
|
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"
|
||||||
|
},
|
||||||
|
"out": "0x",
|
||||||
|
"post": {
|
||||||
|
"Merge": [
|
||||||
|
{
|
||||||
|
"hash": "0xb2cde3c1decab7a146fe0442ed7a8f16e1b044dab737d1196b107c769f86e034",
|
||||||
|
"logs": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"indexes": {
|
||||||
|
"data": 0,
|
||||||
|
"gas": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue