Repository navigation
Use VM registers r3–r5 to pass input metadata to ABIv1 programs #672
Replies: 5 comments
|
We can disqualify To demystify what it's doing, the pattern in its entrypoint is actually a It starts with the first entry in an array of function pointers stored in .rodata
// ...
data_4c00: .quad fn_2708 // ix0
data_4c08: .quad fn_11f8 // ix1
data_4c10: .quad fn_1030 // ix2
data_4c18: .quad fn_30a0 // ix3
data_4c20: .quad fn_0ce8 // ix4
data_4c28: .quad fn_1d48 // ix5
// ...The entrypoint:
// Load number of accounts from `r1` (used as discriminator)
ldxdw r2, [r1+0x0]
// Multiply discriminator by 8 to give an 8-byte stride over .rodata offsets
lsh64 r2, 0x3
// Store value in `data_4c00`, the function pointer to "ix0" in our .rodata
lddw r3, data_4c00
// Compute table_base + discriminator * 8
add64 r3, r2
// Correct off-by-one error to offset for the "signer" account of the instruction
ldxdw r2, [r3-0x8]
// Call ix at corrected offset stored in r2
callx r2
// Exit the program
exitThe |
|
For .globl entrypoint
entrypoint:
stxdw [r10-0xa8], r4 // use of uninitialized register 4
stxdw [r10-0x90], r3 // use of uninitialized register 3
stxdw [r10-0xd8], r1
ldxdw r0, [r5-0xff8] // use of uninitialized register 5 <-- errors out here
jeq r0, 0x0, jmp_0778
ldxdw r5, [r5-0x1000] // use of uninitialized register 5
mov64 r7, 0x0
mov64 r1, r10
add64 r1, -0x38
stxdw [r10-0xe0], r1
mov64 r1, r5
add64 r1, 0x6
stxdw [r10-0x98], r1
stxdw [r10-0xb0], r0
stxdw [r10-0xb8], r5As it stands, the program is not executable, as it will always error out at the 4th instruction: As the offset value from r5 is
None of the above fall within an allocated memory region, so there would be no visible change in behavior for this program as it exists today. |
|
Thanks @deanmlittle for digging into these. I'm good with this change. Ship it. |
|
Looks good to me too. Another simple test you can always do is to implement it, replay against mainnet-beta and then see if it diverges. |
|
Looks good to me! |
Uh oh!
There was an error while loading. Please reload this page.
Motivation
After SIMD-0449 is activated, a slice of account pointers will be serialized into the program input. This eliminates the need to parse the accounts section, but programs must still calculate the offset from the instruction data pointer to the start of the accounts slice.
Proposal
The ABIv1 program entrypoint can use the remaining registers to hold:
r3: instruction data lengthr4: pointer to the accounts slicer5: number of accountsWith these values available in registers, programs can reconstruct the instruction data and accounts slices without calculating offsets or loading their lengths. The VM implementation should require only a minimal change.
Considerations
The program ID still requires an offset calculation. It is located at the instruction data pointer (
r2) plus the instruction data length (r3).Programs should not currently rely on the values in
r3–r5, which are uninitialized at the program entrypoint. An analysis using program-sync (with PR #11) found only one program (4rsQkxtHoEHTzvwoUNt6FTCZjygNemEPZqz9Xeucg3fh) that savesr3andr4to the stack and then dereferencesr5without first assigning values to those registers. The program was deployed four months ago and has not been used since its deployment.Two other programs were flagged:
GdY4puYdZiEfk8HCX7L9kJfzzjc3xSxXrVjKv2vphfDnandfastC7gqs2WUXgcyNna2BZAe9mte4zcTGprv3mv18N3. Their entrypoints contain acallx, and the analyzer assumes that the callee consumes all registers fromr1throughr5. Because the program does not overwrite the initial values ofr4andr5, they are flagged even though their callees do not consume those values.All reactions