Skip to content

Commit 80205c3

Browse files
committed
core-bpf: special-case core bpf program error codes
1 parent 1261e4b commit 80205c3

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

src/lib.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -872,8 +872,21 @@ fn execute_instr(mut input: InstrContext) -> Option<InstrEffects> {
872872
let return_data = transaction_context.get_return_data().1.to_vec();
873873

874874
Some(InstrEffects {
875-
custom_err: if let Err(InstructionError::Custom(x)) = result {
876-
Some(x)
875+
custom_err: if let Err(InstructionError::Custom(code)) = result {
876+
#[cfg(feature = "core-bpf")]
877+
// See comment below under `result` for special-casing of custom
878+
// errors for Core BPF programs.
879+
if program_id == &solana_sdk::address_lookup_table::program::id()
880+
&& (code == 10 || code == 11)
881+
{
882+
None
883+
} else if program_id == &solana_sdk::config::program::id() && (code == 0 || code == 1) {
884+
None
885+
} else {
886+
Some(code)
887+
}
888+
#[cfg(not(feature = "core-bpf"))]
889+
Some(code)
877890
} else {
878891
None
879892
},
@@ -904,6 +917,47 @@ fn execute_instr(mut input: InstrContext) -> Option<InstrEffects> {
904917
{
905918
return InstructionError::ComputationalBudgetExceeded;
906919
}
920+
#[cfg(feature = "core-bpf")]
921+
// Another such error case arises when a program performs a write
922+
// to an account, but the data it writes is the exact same data
923+
// that's currently stored in the account state.
924+
//
925+
// For builtins, the `TransactionContext` is invoked when any write
926+
// is performed, asking it whether or not a write is allowed,
927+
// regardless of the data being written. If the account is not
928+
// writable, it throws `InstructionError::ReadonlyDataModified`.
929+
//
930+
// For BPF programs, writes to readonly accounts are caught _after_
931+
// the VM finishes execution, when the loader inspects the
932+
// serialized input data region. If a write was performed that did
933+
// not modify serialized account state, then no error is thrown.
934+
//
935+
// As a result, Core BPF programs have been outfitted with custom
936+
// errors when `is_writable` checks fail. These errors are
937+
// special-cased below to avoid fixture mismatches.
938+
match err {
939+
InstructionError::Custom(code) => {
940+
if program_id == &solana_sdk::address_lookup_table::program::id() {
941+
// Special-cased custom error codes for the ALT program.
942+
if code == 10 {
943+
return InstructionError::ExecutableDataModified;
944+
}
945+
if code == 11 {
946+
return InstructionError::ReadonlyDataModified;
947+
}
948+
}
949+
if program_id == &solana_sdk::config::program::id() {
950+
// Special-cased custom error codes for the Config program.
951+
if code == 0 {
952+
return InstructionError::ExecutableDataModified;
953+
}
954+
if code == 1 {
955+
return InstructionError::ReadonlyDataModified;
956+
}
957+
}
958+
}
959+
_ => {}
960+
}
907961
err
908962
}),
909963
modified_accounts: transaction_context

0 commit comments

Comments
 (0)