1#![cfg(feature = "agave-unstable-api")]
2#![deny(clippy::arithmetic_side_effects)]
3#![deny(clippy::indexing_slicing)]
4
5#[cfg(feature = "svm-internal")]
6use qualifier_attr::qualifiers;
7use {
8 solana_bincode::limited_deserialize,
9 solana_instruction::AccountMeta,
10 solana_instruction_error::InstructionError,
11 solana_loader_v3_interface::{
12 instruction::{MINIMUM_EXTEND_PROGRAM_BYTES, UpgradeableLoaderInstruction},
13 state::UpgradeableLoaderState,
14 },
15 solana_program_runtime::{
16 deploy_program,
17 invoke_context::InvokeContext,
18 program_cache_entry::{ProgramCacheEntry, ProgramCacheEntryOwner, ProgramCacheEntryType},
19 sysvar_cache::get_sysvar_with_account_check,
20 vm::execute,
21 },
22 solana_pubkey::Pubkey,
23 solana_sbpf::{declare_builtin_function, elf::get_sbpf_version, program::SBPFVersion},
24 solana_sdk_ids::{bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, native_loader},
25 solana_svm_log_collector::{LogCollector, ic_logger_msg},
26 solana_svm_measure::measure::Measure,
27 solana_svm_type_overrides::sync::Arc,
28 solana_system_interface::{MAX_PERMITTED_DATA_LENGTH, instruction as system_instruction},
29 solana_transaction_context::{IndexOfAccount, instruction::InstructionContext},
30 std::{cell::RefCell, rc::Rc},
31 wincode::SchemaRead,
32};
33
34#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
35const DEFAULT_LOADER_COMPUTE_UNITS: u64 = 570;
36#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
37const DEPRECATED_LOADER_COMPUTE_UNITS: u64 = 1_140;
38#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
39const UPGRADEABLE_LOADER_COMPUTE_UNITS: u64 = 2_370;
40
41const WRITE_INSTRUCTION_TAG: [u8; 4] = 1u32.to_le_bytes();
43
44const WRITE_INSTRUCTION_HEADER_LEN: usize = 16;
46
47fn parse_write_instruction(instruction_data: &[u8]) -> Result<(u32, &[u8]), InstructionError> {
48 #[derive(SchemaRead)]
49 struct WriteInstruction<'a> {
50 tag: u32,
51 offset: u32,
52 bytes: &'a [u8],
53 }
54
55 let WriteInstruction { tag, offset, bytes } = wincode::deserialize(instruction_data)
56 .map_err(|_| InstructionError::InvalidInstructionData)?;
57
58 if tag.to_le_bytes() != WRITE_INSTRUCTION_TAG {
59 return Err(InstructionError::InvalidInstructionData);
61 }
62
63 if WRITE_INSTRUCTION_HEADER_LEN.saturating_add(bytes.len()) > solana_packet::PACKET_DATA_SIZE {
64 return Err(InstructionError::InvalidInstructionData);
65 }
66
67 Ok((offset, bytes))
68}
69
70fn write_program_data(
71 program_data_offset: usize,
72 bytes: &[u8],
73 instruction_context: &InstructionContext,
74 log_collector: &Option<Rc<RefCell<LogCollector>>>,
75) -> Result<(), InstructionError> {
76 let mut program = instruction_context.try_borrow_instruction_account(0)?;
77 let data = program.get_data_mut()?;
78 let write_offset = program_data_offset.saturating_add(bytes.len());
79 if data.len() < write_offset {
80 ic_logger_msg!(
81 log_collector,
82 "Write overflow: {} < {}",
83 data.len(),
84 write_offset,
85 );
86 return Err(InstructionError::AccountDataTooSmall);
87 }
88 data.get_mut(program_data_offset..write_offset)
89 .ok_or(InstructionError::AccountDataTooSmall)?
90 .copy_from_slice(bytes);
91 Ok(())
92}
93
94declare_builtin_function!(
95 Entrypoint,
96 fn rust(
97 invoke_context: &mut InvokeContext<'static, 'static>,
98 _arg0: u64,
99 _arg1: u64,
100 _arg2: u64,
101 _arg3: u64,
102 _arg4: u64,
103 ) -> Result<u64, Box<dyn std::error::Error>> {
104 process_instruction_inner(invoke_context)
105 }
106);
107
108mod migration_authority {
109 solana_pubkey::declare_id!("3Scf35jMNk2xXBD6areNjgMtXgp5ZspDhms8vdcbzC42");
110}
111
112#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
113pub(crate) fn process_instruction_inner<'a>(
114 invoke_context: &mut InvokeContext<'a, 'a>,
115) -> Result<u64, Box<dyn std::error::Error>> {
116 let log_collector = invoke_context.get_log_collector();
117 let transaction_context = &invoke_context.transaction_context;
118 let instruction_context = transaction_context.get_current_instruction_context()?;
119 let program_id = instruction_context.get_program_key()?;
120 let owner_id = instruction_context.get_program_owner()?;
121
122 if native_loader::check_id(&owner_id) {
124 let program_id = instruction_context.get_program_key()?;
125 return if bpf_loader_upgradeable::check_id(program_id) {
126 invoke_context
127 .compute_meter
128 .consume_checked(UPGRADEABLE_LOADER_COMPUTE_UNITS)?;
129 process_loader_upgradeable_instruction(invoke_context)
130 } else if bpf_loader::check_id(program_id) {
131 invoke_context
132 .compute_meter
133 .consume_checked(DEFAULT_LOADER_COMPUTE_UNITS)?;
134 ic_logger_msg!(
135 log_collector,
136 "BPF loader management instructions are no longer supported",
137 );
138 Err(InstructionError::UnsupportedProgramId)
139 } else if bpf_loader_deprecated::check_id(program_id) {
140 invoke_context
141 .compute_meter
142 .consume_checked(DEPRECATED_LOADER_COMPUTE_UNITS)?;
143 ic_logger_msg!(log_collector, "Deprecated loader is no longer supported");
144 Err(InstructionError::UnsupportedProgramId)
145 } else {
146 ic_logger_msg!(log_collector, "Invalid BPF loader id");
147 Err(InstructionError::UnsupportedProgramId)
148 }
149 .map(|_| 0)
150 .map_err(|error| Box::new(error) as Box<dyn std::error::Error>);
151 }
152
153 let mut get_or_create_executor_time = Measure::start("get_or_create_executor_time");
155 let executor = invoke_context
156 .program_cache_for_tx_batch
157 .find(program_id)
158 .ok_or_else(|| {
159 ic_logger_msg!(log_collector, "Program is not cached");
160 InstructionError::UnsupportedProgramId
161 })?;
162 get_or_create_executor_time.stop();
163 invoke_context.timings.get_or_create_executor_us += get_or_create_executor_time.as_us();
164
165 match &executor.program {
166 ProgramCacheEntryType::FailedVerification(_)
167 | ProgramCacheEntryType::Closed
168 | ProgramCacheEntryType::DelayVisibility => {
169 ic_logger_msg!(log_collector, "Program is not deployed");
170 Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>)
171 }
172 ProgramCacheEntryType::Loaded(executable) => execute(executable, invoke_context, &executor),
173 _ => Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>),
174 }
175 .map(|_| 0)
176}
177
178fn process_loader_upgradeable_instruction(
179 invoke_context: &mut InvokeContext,
180) -> Result<(), InstructionError> {
181 let log_collector = invoke_context.get_log_collector();
182 let transaction_context = &invoke_context.transaction_context;
183 let instruction_context = transaction_context.get_current_instruction_context()?;
184 let instruction_data = instruction_context.get_instruction_data();
185 let program_id = instruction_context.get_program_key()?;
186
187 let instruction = if instruction_data.starts_with(&WRITE_INSTRUCTION_TAG) {
188 UpgradeableLoaderInstruction::Write {
190 offset: 0,
191 bytes: Vec::new(),
192 }
193 } else {
194 limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)?
195 };
196
197 match instruction {
198 UpgradeableLoaderInstruction::InitializeBuffer => {
199 instruction_context.check_number_of_instruction_accounts(2)?;
200 let mut buffer = instruction_context.try_borrow_instruction_account(0)?;
201
202 if UpgradeableLoaderState::Uninitialized != buffer.get_state()? {
203 ic_logger_msg!(log_collector, "Buffer account already initialized");
204 return Err(InstructionError::AccountAlreadyInitialized);
205 }
206
207 let authority_key = Some(*instruction_context.get_key_of_instruction_account(1)?);
208
209 buffer.set_state(&UpgradeableLoaderState::Buffer {
210 authority_address: authority_key,
211 })?;
212 }
213 UpgradeableLoaderInstruction::Write { .. } => {
214 let (offset, payload) = parse_write_instruction(instruction_data)?;
215 instruction_context.check_number_of_instruction_accounts(2)?;
216 let buffer = instruction_context.try_borrow_instruction_account(0)?;
217
218 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
219 if authority_address.is_none() {
220 ic_logger_msg!(log_collector, "Buffer is immutable");
221 return Err(InstructionError::Immutable); }
223 let authority_key = Some(*instruction_context.get_key_of_instruction_account(1)?);
224 if authority_address != authority_key {
225 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
226 return Err(InstructionError::IncorrectAuthority);
227 }
228 if !instruction_context.is_instruction_account_signer(1)? {
229 ic_logger_msg!(log_collector, "Buffer authority did not sign");
230 return Err(InstructionError::MissingRequiredSignature);
231 }
232 } else {
233 ic_logger_msg!(log_collector, "Invalid Buffer account");
234 return Err(InstructionError::InvalidAccountData);
235 }
236 drop(buffer);
237 write_program_data(
238 UpgradeableLoaderState::size_of_buffer_metadata().saturating_add(offset as usize),
239 payload,
240 &instruction_context,
241 &log_collector,
242 )?;
243 }
244 UpgradeableLoaderInstruction::DeployWithMaxDataLen { max_data_len } => {
245 instruction_context.check_number_of_instruction_accounts(4)?;
246 let payer_key = *instruction_context.get_key_of_instruction_account(0)?;
247 let programdata_key = *instruction_context.get_key_of_instruction_account(1)?;
248 let rent =
249 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 4)?;
250 let clock =
251 get_sysvar_with_account_check::clock(invoke_context, &instruction_context, 5)?;
252 instruction_context.check_number_of_instruction_accounts(8)?;
253 let authority_key = Some(*instruction_context.get_key_of_instruction_account(7)?);
254
255 let program = instruction_context.try_borrow_instruction_account(2)?;
258 if UpgradeableLoaderState::Uninitialized != program.get_state()? {
259 ic_logger_msg!(log_collector, "Program account already initialized");
260 return Err(InstructionError::AccountAlreadyInitialized);
261 }
262 if program.get_data().len() < UpgradeableLoaderState::size_of_program() {
263 ic_logger_msg!(log_collector, "Program account too small");
264 return Err(InstructionError::AccountDataTooSmall);
265 }
266 if program.get_lamports() < rent.minimum_balance(program.get_data().len()) {
267 ic_logger_msg!(log_collector, "Program account not rent-exempt");
268 return Err(InstructionError::ExecutableAccountNotRentExempt);
269 }
270 let new_program_id = *program.get_key();
271 drop(program);
272
273 let buffer = instruction_context.try_borrow_instruction_account(3)?;
276 if !buffer.is_writable() {
277 ic_logger_msg!(log_collector, "Buffer account not writeable");
278 return Err(InstructionError::InvalidArgument);
279 }
280 if buffer.get_owner() != program_id {
281 ic_logger_msg!(log_collector, "Buffer account not owned by loader");
282 return Err(InstructionError::IncorrectProgramId);
283 }
284 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
285 if authority_address != authority_key {
286 ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
287 return Err(InstructionError::IncorrectAuthority);
288 }
289 if !instruction_context.is_instruction_account_signer(7)? {
290 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
291 return Err(InstructionError::MissingRequiredSignature);
292 }
293 } else {
294 ic_logger_msg!(log_collector, "Invalid Buffer account");
295 return Err(InstructionError::InvalidArgument);
296 }
297 let buffer_key = *buffer.get_key();
298 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
299 let buffer_data_len = buffer.get_data().len().saturating_sub(buffer_data_offset);
300 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
301 let programdata_len = UpgradeableLoaderState::size_of_programdata(max_data_len);
302 if buffer.get_data().len() < UpgradeableLoaderState::size_of_buffer_metadata()
303 || buffer_data_len == 0
304 {
305 ic_logger_msg!(log_collector, "Buffer account too small");
306 return Err(InstructionError::InvalidAccountData);
307 }
308 drop(buffer);
309 if max_data_len < buffer_data_len {
310 ic_logger_msg!(
311 log_collector,
312 "Max data length is too small to hold Buffer data"
313 );
314 return Err(InstructionError::AccountDataTooSmall);
315 }
316 if programdata_len > MAX_PERMITTED_DATA_LENGTH as usize {
317 ic_logger_msg!(log_collector, "Max data length is too large");
318 return Err(InstructionError::InvalidArgument);
319 }
320
321 let (derived_address, bump_seed) =
323 Pubkey::find_program_address(&[new_program_id.as_ref()], program_id);
324 if derived_address != programdata_key {
325 ic_logger_msg!(log_collector, "ProgramData address is not derived");
326 return Err(InstructionError::InvalidArgument);
327 }
328
329 {
331 let mut buffer = instruction_context.try_borrow_instruction_account(3)?;
332 let mut payer = instruction_context.try_borrow_instruction_account(0)?;
333 payer.checked_add_lamports(buffer.get_lamports())?;
334 buffer.set_lamports(0)?;
335 }
336
337 let owner_id = *program_id;
338 let mut instruction = system_instruction::create_account(
339 &payer_key,
340 &programdata_key,
341 1.max(rent.minimum_balance(programdata_len)),
342 programdata_len as u64,
343 program_id,
344 );
345
346 instruction
348 .accounts
349 .push(AccountMeta::new(buffer_key, false));
350
351 invoke_context
352 .native_invoke_signed(instruction, &[&[new_program_id.as_ref(), &[bump_seed]]])?;
353
354 let transaction_context = &invoke_context.transaction_context;
356 let instruction_context = transaction_context.get_current_instruction_context()?;
357 let buffer = instruction_context.try_borrow_instruction_account(3)?;
358 deploy_program!(
359 invoke_context,
360 &new_program_id,
361 &owner_id,
362 buffer
363 .get_data()
364 .get(buffer_data_offset..)
365 .ok_or(InstructionError::AccountDataTooSmall)?,
366 clock.slot,
367 invoke_context
368 .get_feature_set()
369 .disable_sbpf_v0_v1_v2_deployment,
370 );
371 drop(buffer);
372
373 let transaction_context = &invoke_context.transaction_context;
374 let instruction_context = transaction_context.get_current_instruction_context()?;
375
376 {
378 let mut programdata = instruction_context.try_borrow_instruction_account(1)?;
379 programdata.set_state(&UpgradeableLoaderState::ProgramData {
380 slot: clock.slot,
381 upgrade_authority_address: authority_key,
382 })?;
383 let dst_slice = programdata
384 .get_data_mut()?
385 .get_mut(
386 programdata_data_offset
387 ..programdata_data_offset.saturating_add(buffer_data_len),
388 )
389 .ok_or(InstructionError::AccountDataTooSmall)?;
390 let mut buffer = instruction_context.try_borrow_instruction_account(3)?;
391 let src_slice = buffer
392 .get_data()
393 .get(buffer_data_offset..)
394 .ok_or(InstructionError::AccountDataTooSmall)?;
395 dst_slice.copy_from_slice(src_slice);
396 buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
397 }
398
399 let mut program = instruction_context.try_borrow_instruction_account(2)?;
401 program.set_state(&UpgradeableLoaderState::Program {
402 programdata_address: programdata_key,
403 })?;
404 program.set_executable(true)?;
405 drop(program);
406
407 ic_logger_msg!(log_collector, "Deployed program {:?}", new_program_id);
408 }
409 UpgradeableLoaderInstruction::Upgrade => {
410 instruction_context.check_number_of_instruction_accounts(3)?;
411 let programdata_key = *instruction_context.get_key_of_instruction_account(0)?;
412 let rent =
413 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 4)?;
414 let clock =
415 get_sysvar_with_account_check::clock(invoke_context, &instruction_context, 5)?;
416 instruction_context.check_number_of_instruction_accounts(7)?;
417 let authority_key = Some(*instruction_context.get_key_of_instruction_account(6)?);
418
419 let set_programdata_to_elf_len = invoke_context
420 .get_feature_set()
421 .loader_v3_set_program_data_to_elf_length;
422
423 let program = instruction_context.try_borrow_instruction_account(1)?;
426 if !program.is_writable() {
427 ic_logger_msg!(log_collector, "Program account not writeable");
428 return Err(InstructionError::InvalidArgument);
429 }
430 if program.get_owner() != program_id {
431 ic_logger_msg!(log_collector, "Program account not owned by loader");
432 return Err(InstructionError::IncorrectProgramId);
433 }
434 if let UpgradeableLoaderState::Program {
435 programdata_address,
436 } = program.get_state()?
437 {
438 if programdata_address != programdata_key {
439 ic_logger_msg!(log_collector, "Program and ProgramData account mismatch");
440 return Err(InstructionError::InvalidArgument);
441 }
442 } else {
443 ic_logger_msg!(log_collector, "Invalid Program account");
444 return Err(InstructionError::InvalidAccountData);
445 }
446 let new_program_id = *program.get_key();
447 drop(program);
448
449 let buffer = instruction_context.try_borrow_instruction_account(2)?;
452 if !buffer.is_writable() {
453 ic_logger_msg!(log_collector, "Buffer account not writeable");
454 return Err(InstructionError::InvalidArgument);
455 }
456 if buffer.get_owner() != program_id {
457 ic_logger_msg!(log_collector, "Buffer account not owned by loader");
458 return Err(InstructionError::IncorrectProgramId);
459 }
460 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
461 if authority_address != authority_key {
462 ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
463 return Err(InstructionError::IncorrectAuthority);
464 }
465 if !instruction_context.is_instruction_account_signer(6)? {
466 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
467 return Err(InstructionError::MissingRequiredSignature);
468 }
469 } else {
470 ic_logger_msg!(log_collector, "Invalid Buffer account");
471 return Err(InstructionError::InvalidArgument);
472 }
473 let buffer_lamports = buffer.get_lamports();
474 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
475 let buffer_data_len = buffer.get_data().len().saturating_sub(buffer_data_offset);
476 if buffer.get_data().len() < UpgradeableLoaderState::size_of_buffer_metadata()
477 || buffer_data_len == 0
478 {
479 ic_logger_msg!(log_collector, "Buffer account too small");
480 return Err(InstructionError::InvalidAccountData);
481 }
482 drop(buffer);
483
484 let programdata = instruction_context.try_borrow_instruction_account(0)?;
487 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
488 let (programdata_len, programdata_balance_required) = if set_programdata_to_elf_len {
489 let new_len = programdata_data_offset.saturating_add(buffer_data_len);
491 if new_len > MAX_PERMITTED_DATA_LENGTH as usize {
492 ic_logger_msg!(
493 log_collector,
494 "Resized ProgramData length of {} bytes exceeds max account data length",
495 new_len
496 );
497 return Err(InstructionError::InvalidAccountData);
498 }
499 (new_len, 1.max(rent.minimum_balance(new_len)))
500 } else {
501 let len = programdata.get_data().len();
504 if len < UpgradeableLoaderState::size_of_programdata(buffer_data_len) {
505 ic_logger_msg!(log_collector, "ProgramData account not large enough");
506 return Err(InstructionError::AccountDataTooSmall);
507 }
508 (len, 1.max(rent.minimum_balance(len)))
509 };
510 if programdata.get_lamports().saturating_add(buffer_lamports)
511 < programdata_balance_required
512 {
513 ic_logger_msg!(
514 log_collector,
515 "Buffer account balance too low to fund upgrade"
516 );
517 return Err(InstructionError::InsufficientFunds);
518 }
519 if let UpgradeableLoaderState::ProgramData {
520 slot,
521 upgrade_authority_address,
522 } = programdata.get_state()?
523 {
524 if clock.slot == slot {
525 ic_logger_msg!(log_collector, "Program was deployed in this block already");
526 return Err(InstructionError::InvalidArgument);
527 }
528 if upgrade_authority_address.is_none() {
529 ic_logger_msg!(log_collector, "Program not upgradeable");
530 return Err(InstructionError::Immutable);
531 }
532 if upgrade_authority_address != authority_key {
533 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
534 return Err(InstructionError::IncorrectAuthority);
535 }
536 if !instruction_context.is_instruction_account_signer(6)? {
537 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
538 return Err(InstructionError::MissingRequiredSignature);
539 }
540 } else {
541 ic_logger_msg!(log_collector, "Invalid ProgramData account");
542 return Err(InstructionError::InvalidAccountData);
543 };
544 drop(programdata);
545
546 let buffer = instruction_context.try_borrow_instruction_account(2)?;
548 deploy_program!(
549 invoke_context,
550 &new_program_id,
551 program_id,
552 buffer
553 .get_data()
554 .get(buffer_data_offset..)
555 .ok_or(InstructionError::AccountDataTooSmall)?,
556 clock.slot,
557 invoke_context
558 .get_feature_set()
559 .disable_sbpf_v0_v1_v2_deployment,
560 );
561 drop(buffer);
562
563 let transaction_context = &invoke_context.transaction_context;
564 let instruction_context = transaction_context.get_current_instruction_context()?;
565
566 let mut programdata = instruction_context.try_borrow_instruction_account(0)?;
568 {
569 programdata.set_data_length(programdata_len)?;
570 programdata.set_state(&UpgradeableLoaderState::ProgramData {
571 slot: clock.slot,
572 upgrade_authority_address: authority_key,
573 })?;
574 let dst_slice = programdata
575 .get_data_mut()?
576 .get_mut(
577 programdata_data_offset
578 ..programdata_data_offset.saturating_add(buffer_data_len),
579 )
580 .ok_or(InstructionError::AccountDataTooSmall)?;
581 let buffer = instruction_context.try_borrow_instruction_account(2)?;
582 let src_slice = buffer
583 .get_data()
584 .get(buffer_data_offset..)
585 .ok_or(InstructionError::AccountDataTooSmall)?;
586 dst_slice.copy_from_slice(src_slice);
587 }
588 programdata
589 .get_data_mut()?
590 .get_mut(programdata_data_offset.saturating_add(buffer_data_len)..)
591 .ok_or(InstructionError::AccountDataTooSmall)?
592 .fill(0);
593
594 let mut buffer = instruction_context.try_borrow_instruction_account(2)?;
596 let mut spill = instruction_context.try_borrow_instruction_account(3)?;
597 spill.checked_add_lamports(
598 programdata
599 .get_lamports()
600 .saturating_add(buffer_lamports)
601 .saturating_sub(programdata_balance_required),
602 )?;
603 buffer.set_lamports(0)?;
604 programdata.set_lamports(programdata_balance_required)?;
605 buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
606
607 ic_logger_msg!(log_collector, "Upgraded program {:?}", new_program_id);
608 }
609 UpgradeableLoaderInstruction::SetAuthority => {
610 instruction_context.check_number_of_instruction_accounts(2)?;
611 let mut account = instruction_context.try_borrow_instruction_account(0)?;
612 let present_authority_key = instruction_context.get_key_of_instruction_account(1)?;
613 let new_authority = instruction_context.get_key_of_instruction_account(2).ok();
614
615 match account.get_state()? {
616 UpgradeableLoaderState::Buffer { authority_address } => {
617 if new_authority.is_none() {
618 ic_logger_msg!(log_collector, "Buffer authority is not optional");
619 return Err(InstructionError::IncorrectAuthority);
620 }
621 if authority_address.is_none() {
622 ic_logger_msg!(log_collector, "Buffer is immutable");
623 return Err(InstructionError::Immutable);
624 }
625 if authority_address != Some(*present_authority_key) {
626 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
627 return Err(InstructionError::IncorrectAuthority);
628 }
629 if !instruction_context.is_instruction_account_signer(1)? {
630 ic_logger_msg!(log_collector, "Buffer authority did not sign");
631 return Err(InstructionError::MissingRequiredSignature);
632 }
633 account.set_state(&UpgradeableLoaderState::Buffer {
634 authority_address: new_authority.cloned(),
635 })?;
636 }
637 UpgradeableLoaderState::ProgramData {
638 slot,
639 upgrade_authority_address,
640 } => {
641 if upgrade_authority_address.is_none() {
642 ic_logger_msg!(log_collector, "Program not upgradeable");
643 return Err(InstructionError::Immutable);
644 }
645 if upgrade_authority_address != Some(*present_authority_key) {
646 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
647 return Err(InstructionError::IncorrectAuthority);
648 }
649 if !instruction_context.is_instruction_account_signer(1)? {
650 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
651 return Err(InstructionError::MissingRequiredSignature);
652 }
653 if invoke_context
654 .get_feature_set()
655 .disable_sbpf_v0_v1_v2_deployment
656 && new_authority.is_none()
657 && let Some(program) = account
658 .get_data()
659 .get(UpgradeableLoaderState::size_of_programdata_metadata()..)
660 && let Ok(sbpf_version) = get_sbpf_version(program)
661 && sbpf_version < SBPFVersion::V3
662 {
663 return Err(InstructionError::InvalidAccountData);
664 }
665 account.set_state(&UpgradeableLoaderState::ProgramData {
666 slot,
667 upgrade_authority_address: new_authority.cloned(),
668 })?;
669 }
670 _ => {
671 ic_logger_msg!(log_collector, "Account does not support authorities");
672 return Err(InstructionError::InvalidArgument);
673 }
674 }
675
676 ic_logger_msg!(log_collector, "New authority {:?}", new_authority);
677 }
678 UpgradeableLoaderInstruction::SetAuthorityChecked => {
679 if !invoke_context
680 .get_feature_set()
681 .enable_bpf_loader_set_authority_checked_ix
682 {
683 return Err(InstructionError::InvalidInstructionData);
684 }
685
686 instruction_context.check_number_of_instruction_accounts(3)?;
687 let mut account = instruction_context.try_borrow_instruction_account(0)?;
688 let present_authority_key = instruction_context.get_key_of_instruction_account(1)?;
689 let new_authority_key = instruction_context.get_key_of_instruction_account(2)?;
690
691 match account.get_state()? {
692 UpgradeableLoaderState::Buffer { authority_address } => {
693 if authority_address.is_none() {
694 ic_logger_msg!(log_collector, "Buffer is immutable");
695 return Err(InstructionError::Immutable);
696 }
697 if authority_address != Some(*present_authority_key) {
698 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
699 return Err(InstructionError::IncorrectAuthority);
700 }
701 if !instruction_context.is_instruction_account_signer(1)? {
702 ic_logger_msg!(log_collector, "Buffer authority did not sign");
703 return Err(InstructionError::MissingRequiredSignature);
704 }
705 if !instruction_context.is_instruction_account_signer(2)? {
706 ic_logger_msg!(log_collector, "New authority did not sign");
707 return Err(InstructionError::MissingRequiredSignature);
708 }
709 account.set_state(&UpgradeableLoaderState::Buffer {
710 authority_address: Some(*new_authority_key),
711 })?;
712 }
713 UpgradeableLoaderState::ProgramData {
714 slot,
715 upgrade_authority_address,
716 } => {
717 if upgrade_authority_address.is_none() {
718 ic_logger_msg!(log_collector, "Program not upgradeable");
719 return Err(InstructionError::Immutable);
720 }
721 if upgrade_authority_address != Some(*present_authority_key) {
722 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
723 return Err(InstructionError::IncorrectAuthority);
724 }
725 if !instruction_context.is_instruction_account_signer(1)? {
726 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
727 return Err(InstructionError::MissingRequiredSignature);
728 }
729 if !instruction_context.is_instruction_account_signer(2)? {
730 ic_logger_msg!(log_collector, "New authority did not sign");
731 return Err(InstructionError::MissingRequiredSignature);
732 }
733 account.set_state(&UpgradeableLoaderState::ProgramData {
734 slot,
735 upgrade_authority_address: Some(*new_authority_key),
736 })?;
737 }
738 _ => {
739 ic_logger_msg!(log_collector, "Account does not support authorities");
740 return Err(InstructionError::InvalidArgument);
741 }
742 }
743
744 ic_logger_msg!(log_collector, "New authority {:?}", new_authority_key);
745 }
746 UpgradeableLoaderInstruction::Close => {
747 instruction_context.check_number_of_instruction_accounts(2)?;
748 if instruction_context.get_index_of_instruction_account_in_transaction(0)?
749 == instruction_context.get_index_of_instruction_account_in_transaction(1)?
750 {
751 ic_logger_msg!(
752 log_collector,
753 "Recipient is the same as the account being closed"
754 );
755 return Err(InstructionError::InvalidArgument);
756 }
757 let mut close_account = instruction_context.try_borrow_instruction_account(0)?;
758 let close_key = *close_account.get_key();
759 let close_account_state = close_account.get_state()?;
760 match close_account_state {
761 UpgradeableLoaderState::Uninitialized => {
762 let mut recipient_account =
763 instruction_context.try_borrow_instruction_account(1)?;
764 recipient_account.checked_add_lamports(close_account.get_lamports())?;
765 close_account.set_lamports(0)?;
766 close_account
767 .set_data_length(UpgradeableLoaderState::size_of_uninitialized())?;
768 ic_logger_msg!(log_collector, "Closed Uninitialized {}", close_key);
769 }
770 UpgradeableLoaderState::Buffer { authority_address } => {
771 instruction_context.check_number_of_instruction_accounts(3)?;
772 drop(close_account);
773 common_close_account(&authority_address, &instruction_context, &log_collector)?;
774 ic_logger_msg!(log_collector, "Closed Buffer {}", close_key);
775 }
776 UpgradeableLoaderState::ProgramData {
777 slot,
778 upgrade_authority_address: authority_address,
779 } => {
780 instruction_context.check_number_of_instruction_accounts(4)?;
781 drop(close_account);
782 let program_account = instruction_context.try_borrow_instruction_account(3)?;
783 let program_key = *program_account.get_key();
784
785 if !program_account.is_writable() {
786 ic_logger_msg!(log_collector, "Program account is not writable");
787 return Err(InstructionError::InvalidArgument);
788 }
789 if program_account.get_owner() != program_id {
790 ic_logger_msg!(log_collector, "Program account not owned by loader");
791 return Err(InstructionError::IncorrectProgramId);
792 }
793 let clock = invoke_context
794 .environment_config
795 .sysvar_cache()
796 .get_clock()?;
797 if clock.slot == slot {
798 ic_logger_msg!(log_collector, "Program was deployed in this block already");
799 return Err(InstructionError::InvalidArgument);
800 }
801
802 match program_account.get_state()? {
803 UpgradeableLoaderState::Program {
804 programdata_address,
805 } => {
806 if programdata_address != close_key {
807 ic_logger_msg!(
808 log_collector,
809 "ProgramData account does not match ProgramData account"
810 );
811 return Err(InstructionError::InvalidArgument);
812 }
813
814 drop(program_account);
815 common_close_account(
816 &authority_address,
817 &instruction_context,
818 &log_collector,
819 )?;
820 let clock = invoke_context
821 .environment_config
822 .sysvar_cache()
823 .get_clock()?;
824 invoke_context
825 .program_cache_for_tx_batch
826 .store_modified_entry(
827 program_key,
828 Arc::new(ProgramCacheEntry::new_closed_tombstone(
829 clock.slot,
830 ProgramCacheEntryOwner::LoaderV3,
831 )),
832 );
833 }
834 _ => {
835 ic_logger_msg!(log_collector, "Invalid Program account");
836 return Err(InstructionError::InvalidArgument);
837 }
838 }
839
840 ic_logger_msg!(log_collector, "Closed Program {}", program_key);
841 }
842 _ => {
843 ic_logger_msg!(log_collector, "Account does not support closing");
844 return Err(InstructionError::InvalidArgument);
845 }
846 }
847 }
848 UpgradeableLoaderInstruction::ExtendProgram { additional_bytes } => {
849 common_extend_program(invoke_context, additional_bytes, false)?;
850 }
851 }
852
853 Ok(())
854}
855
856fn common_extend_program(
857 invoke_context: &mut InvokeContext,
858 additional_bytes: u32,
859 check_authority: bool,
860) -> Result<(), InstructionError> {
861 let log_collector = invoke_context.get_log_collector();
862 let transaction_context = &invoke_context.transaction_context;
863 let instruction_context = transaction_context.get_current_instruction_context()?;
864 let program_id = instruction_context.get_program_key()?;
865
866 const PROGRAM_DATA_ACCOUNT_INDEX: IndexOfAccount = 0;
867 const PROGRAM_ACCOUNT_INDEX: IndexOfAccount = 1;
868 const AUTHORITY_ACCOUNT_INDEX: IndexOfAccount = 2;
869 let optional_payer_account_index = if check_authority { 4 } else { 3 };
871
872 if additional_bytes == 0 {
873 ic_logger_msg!(log_collector, "Additional bytes must be greater than 0");
874 return Err(InstructionError::InvalidInstructionData);
875 }
876
877 let programdata_account =
878 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
879 let programdata_key = *programdata_account.get_key();
880
881 if program_id != programdata_account.get_owner() {
882 ic_logger_msg!(log_collector, "ProgramData owner is invalid");
883 return Err(InstructionError::InvalidAccountOwner);
884 }
885 if !programdata_account.is_writable() {
886 ic_logger_msg!(log_collector, "ProgramData is not writable");
887 return Err(InstructionError::InvalidArgument);
888 }
889
890 let program_account =
891 instruction_context.try_borrow_instruction_account(PROGRAM_ACCOUNT_INDEX)?;
892 if !program_account.is_writable() {
893 ic_logger_msg!(log_collector, "Program account is not writable");
894 return Err(InstructionError::InvalidArgument);
895 }
896 if program_account.get_owner() != program_id {
897 ic_logger_msg!(log_collector, "Program account not owned by loader");
898 return Err(InstructionError::InvalidAccountOwner);
899 }
900 let program_key = *program_account.get_key();
901 match program_account.get_state()? {
902 UpgradeableLoaderState::Program {
903 programdata_address,
904 } => {
905 if programdata_address != programdata_key {
906 ic_logger_msg!(
907 log_collector,
908 "Program account does not match ProgramData account"
909 );
910 return Err(InstructionError::InvalidArgument);
911 }
912 }
913 _ => {
914 ic_logger_msg!(log_collector, "Invalid Program account");
915 return Err(InstructionError::InvalidAccountData);
916 }
917 }
918 drop(program_account);
919
920 let old_len = programdata_account.get_data().len();
921 let new_len = old_len.saturating_add(additional_bytes as usize);
922 if new_len > MAX_PERMITTED_DATA_LENGTH as usize {
923 ic_logger_msg!(
924 log_collector,
925 "Extended ProgramData length of {} bytes exceeds max account data length of {} bytes",
926 new_len,
927 MAX_PERMITTED_DATA_LENGTH
928 );
929 return Err(InstructionError::InvalidRealloc);
930 }
931
932 if invoke_context
933 .get_feature_set()
934 .loader_v3_minimum_extend_program_size
935 {
936 let headroom = (MAX_PERMITTED_DATA_LENGTH as usize).saturating_sub(old_len);
942 if additional_bytes < MINIMUM_EXTEND_PROGRAM_BYTES
943 && (additional_bytes as usize) != headroom
944 {
945 ic_logger_msg!(
946 log_collector,
947 "ExtendProgram requires a minimum of {} additional bytes or to extend to maximum \
948 size, but only {} were requested",
949 MINIMUM_EXTEND_PROGRAM_BYTES,
950 additional_bytes,
951 );
952 return Err(InstructionError::InvalidArgument);
953 }
954 }
955
956 let clock_slot = invoke_context
957 .environment_config
958 .sysvar_cache()
959 .get_clock()
960 .map(|clock| clock.slot)?;
961
962 let upgrade_authority_address = if let UpgradeableLoaderState::ProgramData {
963 slot,
964 upgrade_authority_address,
965 } = programdata_account.get_state()?
966 {
967 if clock_slot == slot {
968 ic_logger_msg!(log_collector, "Program was extended in this block already");
969 return Err(InstructionError::InvalidArgument);
970 }
971
972 if upgrade_authority_address.is_none() {
973 ic_logger_msg!(
974 log_collector,
975 "Cannot extend ProgramData accounts that are not upgradeable"
976 );
977 return Err(InstructionError::Immutable);
978 }
979
980 if check_authority {
981 let authority_key =
982 Some(*instruction_context.get_key_of_instruction_account(AUTHORITY_ACCOUNT_INDEX)?);
983 if upgrade_authority_address != authority_key {
984 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
985 return Err(InstructionError::IncorrectAuthority);
986 }
987 if !instruction_context.is_instruction_account_signer(AUTHORITY_ACCOUNT_INDEX)? {
988 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
989 return Err(InstructionError::MissingRequiredSignature);
990 }
991 }
992
993 upgrade_authority_address
994 } else {
995 ic_logger_msg!(log_collector, "ProgramData state is invalid");
996 return Err(InstructionError::InvalidAccountData);
997 };
998
999 let required_payment = {
1000 let balance = programdata_account.get_lamports();
1001 let rent = invoke_context
1002 .environment_config
1003 .sysvar_cache()
1004 .get_rent()?;
1005 let min_balance = rent.minimum_balance(new_len).max(1);
1006 min_balance.saturating_sub(balance)
1007 };
1008
1009 drop(programdata_account);
1011
1012 let program_id = *program_id;
1014 if required_payment > 0 {
1015 let payer_key =
1016 *instruction_context.get_key_of_instruction_account(optional_payer_account_index)?;
1017
1018 invoke_context.native_invoke_signed(
1019 system_instruction::transfer(&payer_key, &programdata_key, required_payment),
1020 &[],
1021 )?;
1022 }
1023
1024 let transaction_context = &invoke_context.transaction_context;
1025 let instruction_context = transaction_context.get_current_instruction_context()?;
1026 let mut programdata_account =
1027 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
1028 programdata_account.set_data_length(new_len)?;
1029
1030 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
1031
1032 deploy_program!(
1033 invoke_context,
1034 &program_key,
1035 &program_id,
1036 programdata_account
1037 .get_data()
1038 .get(programdata_data_offset..)
1039 .ok_or(InstructionError::AccountDataTooSmall)?,
1040 clock_slot,
1041 false, );
1043 drop(programdata_account);
1044
1045 let mut programdata_account =
1046 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
1047 programdata_account.set_state(&UpgradeableLoaderState::ProgramData {
1048 slot: clock_slot,
1049 upgrade_authority_address,
1050 })?;
1051
1052 ic_logger_msg!(
1053 log_collector,
1054 "Extended ProgramData account by {} bytes",
1055 additional_bytes
1056 );
1057
1058 Ok(())
1059}
1060
1061fn common_close_account(
1062 authority_address: &Option<Pubkey>,
1063 instruction_context: &InstructionContext,
1064 log_collector: &Option<Rc<RefCell<LogCollector>>>,
1065) -> Result<(), InstructionError> {
1066 if authority_address.is_none() {
1067 ic_logger_msg!(log_collector, "Account is immutable");
1068 return Err(InstructionError::Immutable);
1069 }
1070 if *authority_address != Some(*instruction_context.get_key_of_instruction_account(2)?) {
1071 ic_logger_msg!(log_collector, "Incorrect authority provided");
1072 return Err(InstructionError::IncorrectAuthority);
1073 }
1074 if !instruction_context.is_instruction_account_signer(2)? {
1075 ic_logger_msg!(log_collector, "Authority did not sign");
1076 return Err(InstructionError::MissingRequiredSignature);
1077 }
1078
1079 let mut close_account = instruction_context.try_borrow_instruction_account(0)?;
1080 let mut recipient_account = instruction_context.try_borrow_instruction_account(1)?;
1081
1082 recipient_account.checked_add_lamports(close_account.get_lamports())?;
1083 close_account.set_lamports(0)?;
1084 close_account.set_data_length(UpgradeableLoaderState::size_of_uninitialized())?;
1085 close_account.set_state(&UpgradeableLoaderState::Uninitialized)?;
1086 Ok(())
1087}
1088
1089#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
1090mod test_utils {
1091 #[cfg(all(feature = "svm-internal", feature = "metrics"))]
1092 use solana_program_runtime::program_metrics::LoadProgramMetrics;
1093 #[cfg(feature = "svm-internal")]
1094 use {
1095 super::*, solana_account::ReadableAccount,
1096 solana_program_runtime::loaded_programs::ProgramRuntimeEnvironment,
1097 solana_syscalls::create_program_runtime_environment,
1098 };
1099
1100 #[cfg(feature = "svm-internal")]
1101 fn check_loader_id(id: &Pubkey) -> bool {
1102 bpf_loader::check_id(id)
1103 || bpf_loader_deprecated::check_id(id)
1104 || bpf_loader_upgradeable::check_id(id)
1105 }
1106
1107 #[cfg(feature = "svm-internal")]
1108 #[cfg_attr(feature = "svm-internal", qualifiers(pub))]
1109 fn load_all_invoked_programs(invoke_context: &mut InvokeContext) {
1110 let program_runtime_environment = create_program_runtime_environment(
1111 invoke_context.get_feature_set(),
1112 invoke_context.get_compute_budget(),
1113 false, false, )
1116 .unwrap();
1117 let num_accounts = invoke_context.transaction_context.get_number_of_accounts();
1118 for index in 0..num_accounts {
1119 let account = invoke_context
1120 .transaction_context
1121 .accounts()
1122 .try_borrow(index)
1123 .expect("Failed to get the account");
1124
1125 let owner = account.owner();
1126 if check_loader_id(owner) {
1127 let programdata_data_offset = 0;
1128 let pubkey = invoke_context
1129 .transaction_context
1130 .get_key_of_account_at_index(index)
1131 .expect("Failed to get account key");
1132
1133 let programdata = account
1134 .data()
1135 .get(programdata_data_offset.min(account.data().len())..)
1136 .unwrap();
1137 let loaded_program = ProgramCacheEntry::load(
1138 owner,
1139 ProgramRuntimeEnvironment::clone(&program_runtime_environment),
1140 0,
1141 programdata,
1142 #[cfg(feature = "metrics")]
1143 &mut LoadProgramMetrics::default(),
1144 )
1145 .map_err(|_| InstructionError::InvalidAccountData);
1146 if let Ok(loaded_program) = loaded_program {
1147 invoke_context
1148 .program_cache_for_tx_batch
1149 .store_modified_entry(*pubkey, Arc::new(loaded_program));
1150 }
1151 }
1152 }
1153 }
1154}
1155
1156#[cfg(test)]
1157mod tests {
1158 use {
1159 super::*,
1160 assert_matches::assert_matches,
1161 rand::Rng,
1162 solana_account::{
1163 AccountSharedData, ReadableAccount, WritableAccount,
1164 state_traits::StateMutWincode as StateMut,
1165 },
1166 solana_clock::Clock,
1167 solana_epoch_schedule::EpochSchedule,
1168 solana_instruction::AccountMeta,
1169 solana_instruction_error::InstructionError,
1170 solana_program_runtime::{
1171 invoke_context::mock_process_instruction_with_feature_set,
1172 loaded_programs::ProgramRuntimeEnvironment, program_metrics::ProgramStatistics,
1173 vm::calculate_heap_cost, with_mock_invoke_context,
1174 },
1175 solana_pubkey::Pubkey,
1176 solana_rent::Rent,
1177 solana_sbpf::program::{BuiltinFunctionDefinition, BuiltinProgram},
1178 solana_sdk_ids::{system_program, sysvar},
1179 solana_svm_feature_set::SVMFeatureSet,
1180 solana_svm_type_overrides::sync::atomic::{AtomicU64, Ordering},
1181 solana_sysvar_id::SysvarId,
1182 std::{fs::File, io::Read, ops::Range},
1183 test_case::test_case,
1184 };
1185
1186 #[derive(Clone, Copy)]
1187 struct LoaderV3Features {
1188 pub set_programdata_to_elf_length: bool,
1190 }
1191
1192 impl LoaderV3Features {
1193 fn all_enabled() -> Self {
1194 Self {
1195 set_programdata_to_elf_length: true,
1196 }
1197 }
1198 }
1199
1200 fn setup_features(feature_set: &mut SVMFeatureSet, loader_v3_features: LoaderV3Features) {
1201 let LoaderV3Features {
1202 set_programdata_to_elf_length,
1203 } = loader_v3_features;
1204 feature_set.loader_v3_set_program_data_to_elf_length = set_programdata_to_elf_length;
1205 }
1206
1207 fn create_sysvar_account<T>(value: &T) -> AccountSharedData
1208 where
1209 T: wincode::Serialize<Src = T> + SysvarId,
1210 {
1211 let serialized_len = wincode::serialized_size(value).unwrap() as usize;
1212 let canonical_data_len = match T::id() {
1213 sysvar::clock::ID => solana_clock::SIZE,
1214 sysvar::epoch_schedule::ID => solana_epoch_schedule::SIZE,
1215 sysvar::rent::ID => solana_rent::SIZE,
1216 id => panic!("unsupported sysvar: {id}"),
1217 };
1218 let required_data_len = canonical_data_len.max(serialized_len);
1219 let mut account = AccountSharedData::new(1, required_data_len, &sysvar::id());
1220 wincode::serialize_into(account.data_as_mut_slice(), value).unwrap();
1221 account
1222 }
1223
1224 #[cfg(feature = "shuttle-test")]
1230 const MOCK_PROCESS_RANDOM_ITERATIONS: usize = 10;
1231
1232 fn process_instruction_with_setup(
1255 program_id: &Pubkey,
1256 instruction_data: &[u8],
1257 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1258 instruction_accounts: Vec<AccountMeta>,
1259 loader_v3_features: LoaderV3Features,
1260 expected_result: Result<(), InstructionError>,
1261 setup: fn(&mut InvokeContext),
1262 ) -> Vec<AccountSharedData> {
1263 let mut feature_set = SVMFeatureSet::all_enabled();
1264 setup_features(&mut feature_set, loader_v3_features);
1265
1266 #[cfg(feature = "shuttle-test")]
1267 {
1268 let program_id = *program_id;
1269 let instruction_data = instruction_data.to_vec();
1270 let result = shuttle::sync::Arc::new(shuttle::sync::Mutex::new(None));
1271 let result_for_test = shuttle::sync::Arc::clone(&result);
1272 shuttle::check_random(
1273 move || {
1274 let accounts = mock_process_instruction_with_feature_set(
1275 &program_id,
1276 &instruction_data,
1277 transaction_accounts.clone(),
1278 instruction_accounts.clone(),
1279 expected_result.clone(),
1280 Entrypoint::register,
1281 setup,
1282 |_invoke_context| {},
1283 &feature_set,
1284 );
1285 *result_for_test.lock().unwrap() = Some(accounts);
1286 },
1287 MOCK_PROCESS_RANDOM_ITERATIONS,
1288 );
1289
1290 let Ok(mut result) = shuttle::sync::Arc::try_unwrap(result) else {
1293 panic!("shuttle test result still has outstanding references")
1294 };
1295 result
1296 .get_mut()
1297 .unwrap()
1298 .take()
1299 .expect("shuttle test did not produce a result")
1300 }
1301
1302 #[cfg(not(feature = "shuttle-test"))]
1303 mock_process_instruction_with_feature_set(
1304 program_id,
1305 instruction_data,
1306 transaction_accounts,
1307 instruction_accounts,
1308 expected_result,
1309 Entrypoint::register,
1310 setup,
1311 |_invoke_context| {},
1312 &feature_set,
1313 )
1314 }
1315
1316 fn process_instruction(
1317 program_id: &Pubkey,
1318 instruction_data: &[u8],
1319 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1320 instruction_accounts: Vec<AccountMeta>,
1321 expected_result: Result<(), InstructionError>,
1322 ) -> Vec<AccountSharedData> {
1323 process_instruction_with_setup(
1324 program_id,
1325 instruction_data,
1326 transaction_accounts,
1327 instruction_accounts,
1328 LoaderV3Features::all_enabled(),
1329 expected_result,
1330 |invoke_context| {
1331 test_utils::load_all_invoked_programs(invoke_context);
1332 },
1333 )
1334 }
1335
1336 fn load_program_account_from_elf(loader_id: &Pubkey, path: &str) -> AccountSharedData {
1337 let mut file = File::open(path).expect("file open failed");
1338 let mut elf = Vec::new();
1339 file.read_to_end(&mut elf).unwrap();
1340 let rent = Rent::default();
1341 let mut program_account =
1342 AccountSharedData::new(rent.minimum_balance(elf.len()), 0, loader_id);
1343 program_account.set_data_from_slice(&elf);
1344 program_account.set_executable(true);
1345 program_account
1346 }
1347
1348 #[test]
1349 fn test_bpf_loader_invoke_main() {
1350 let loader_id = bpf_loader::id();
1351 let program_id = Pubkey::new_unique();
1352 let program_account =
1353 load_program_account_from_elf(&loader_id, "test_elfs/out/sbpfv3_return_ok.so");
1354 let parameter_id = Pubkey::new_unique();
1355 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1356 let parameter_meta = AccountMeta {
1357 pubkey: parameter_id,
1358 is_signer: false,
1359 is_writable: false,
1360 };
1361
1362 process_instruction(
1364 &loader_id,
1365 &[],
1366 Vec::new(),
1367 Vec::new(),
1368 Err(InstructionError::UnsupportedProgramId),
1369 );
1370
1371 process_instruction(
1373 &program_id,
1374 &[],
1375 vec![(program_id, program_account.clone())],
1376 Vec::new(),
1377 Ok(()),
1378 );
1379
1380 process_instruction(
1382 &program_id,
1383 &[],
1384 vec![
1385 (program_id, program_account.clone()),
1386 (parameter_id, parameter_account.clone()),
1387 ],
1388 vec![parameter_meta.clone()],
1389 Ok(()),
1390 );
1391
1392 process_instruction(
1394 &program_id,
1395 &[],
1396 vec![
1397 (program_id, program_account.clone()),
1398 (parameter_id, parameter_account.clone()),
1399 ],
1400 vec![parameter_meta.clone(), parameter_meta],
1401 Ok(()),
1402 );
1403
1404 process_instruction_with_setup(
1406 &program_id,
1407 &[],
1408 vec![(program_id, program_account)],
1409 Vec::new(),
1410 LoaderV3Features::all_enabled(),
1411 Err(InstructionError::ProgramFailedToComplete),
1412 |invoke_context| {
1413 invoke_context.compute_meter.mock_set_remaining(0);
1414 test_utils::load_all_invoked_programs(invoke_context);
1415 },
1416 );
1417
1418 process_instruction_with_setup(
1420 &program_id,
1421 &[],
1422 vec![(program_id, parameter_account.clone())],
1423 Vec::new(),
1424 LoaderV3Features::all_enabled(),
1425 Err(InstructionError::UnsupportedProgramId),
1426 |invoke_context| {
1427 test_utils::load_all_invoked_programs(invoke_context);
1428 },
1429 );
1430 process_instruction(
1431 &program_id,
1432 &[],
1433 vec![(program_id, parameter_account)],
1434 Vec::new(),
1435 Err(InstructionError::UnsupportedProgramId),
1436 );
1437 }
1438
1439 #[test]
1440 fn test_bpf_loader_serialize_unaligned() {
1441 let loader_id = bpf_loader_deprecated::id();
1442 let program_id = Pubkey::new_unique();
1443 let program_account =
1444 load_program_account_from_elf(&loader_id, "test_elfs/out/noop_unaligned.so");
1445 let parameter_id = Pubkey::new_unique();
1446 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1447 let parameter_meta = AccountMeta {
1448 pubkey: parameter_id,
1449 is_signer: false,
1450 is_writable: false,
1451 };
1452
1453 process_instruction(
1455 &program_id,
1456 &[],
1457 vec![
1458 (program_id, program_account.clone()),
1459 (parameter_id, parameter_account.clone()),
1460 ],
1461 vec![parameter_meta.clone()],
1462 Ok(()),
1463 );
1464
1465 process_instruction(
1467 &program_id,
1468 &[],
1469 vec![
1470 (program_id, program_account),
1471 (parameter_id, parameter_account),
1472 ],
1473 vec![parameter_meta.clone(), parameter_meta],
1474 Ok(()),
1475 );
1476 }
1477
1478 #[test]
1479 fn test_bpf_loader_serialize_aligned() {
1480 let loader_id = bpf_loader::id();
1481 let program_id = Pubkey::new_unique();
1482 let program_account =
1483 load_program_account_from_elf(&loader_id, "test_elfs/out/noop_aligned.so");
1484 let parameter_id = Pubkey::new_unique();
1485 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1486 let parameter_meta = AccountMeta {
1487 pubkey: parameter_id,
1488 is_signer: false,
1489 is_writable: false,
1490 };
1491
1492 process_instruction(
1494 &program_id,
1495 &[],
1496 vec![
1497 (program_id, program_account.clone()),
1498 (parameter_id, parameter_account.clone()),
1499 ],
1500 vec![parameter_meta.clone()],
1501 Ok(()),
1502 );
1503
1504 process_instruction(
1506 &program_id,
1507 &[],
1508 vec![
1509 (program_id, program_account),
1510 (parameter_id, parameter_account),
1511 ],
1512 vec![parameter_meta.clone(), parameter_meta],
1513 Ok(()),
1514 );
1515 }
1516
1517 #[test]
1518 fn test_bpf_loader_upgradeable_initialize_buffer() {
1519 let loader_id = bpf_loader_upgradeable::id();
1520 let buffer_address = Pubkey::new_unique();
1521 let buffer_account =
1522 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1523 let authority_address = Pubkey::new_unique();
1524 let authority_account =
1525 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1526 let instruction_data =
1527 bincode::serialize(&UpgradeableLoaderInstruction::InitializeBuffer).unwrap();
1528 let instruction_accounts = vec![
1529 AccountMeta {
1530 pubkey: buffer_address,
1531 is_signer: false,
1532 is_writable: true,
1533 },
1534 AccountMeta {
1535 pubkey: authority_address,
1536 is_signer: false,
1537 is_writable: false,
1538 },
1539 ];
1540
1541 let accounts = process_instruction(
1543 &loader_id,
1544 &instruction_data,
1545 vec![
1546 (buffer_address, buffer_account),
1547 (authority_address, authority_account),
1548 ],
1549 instruction_accounts.clone(),
1550 Ok(()),
1551 );
1552 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1553 assert_eq!(
1554 state,
1555 UpgradeableLoaderState::Buffer {
1556 authority_address: Some(authority_address)
1557 }
1558 );
1559
1560 let accounts = process_instruction(
1562 &loader_id,
1563 &instruction_data,
1564 vec![
1565 (buffer_address, accounts.first().unwrap().clone()),
1566 (authority_address, accounts.get(1).unwrap().clone()),
1567 ],
1568 instruction_accounts,
1569 Err(InstructionError::AccountAlreadyInitialized),
1570 );
1571 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1572 assert_eq!(
1573 state,
1574 UpgradeableLoaderState::Buffer {
1575 authority_address: Some(authority_address)
1576 }
1577 );
1578 }
1579
1580 #[test]
1581 fn test_bpf_loader_upgradeable_write() {
1582 let loader_id = bpf_loader_upgradeable::id();
1583 let buffer_address = Pubkey::new_unique();
1584 let mut buffer_account =
1585 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1586 let instruction_accounts = vec![
1587 AccountMeta {
1588 pubkey: buffer_address,
1589 is_signer: false,
1590 is_writable: true,
1591 },
1592 AccountMeta {
1593 pubkey: buffer_address,
1594 is_signer: true,
1595 is_writable: false,
1596 },
1597 ];
1598
1599 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1601 offset: 0,
1602 bytes: vec![42; 9],
1603 })
1604 .unwrap();
1605 process_instruction(
1606 &loader_id,
1607 &instruction,
1608 vec![(buffer_address, buffer_account.clone())],
1609 instruction_accounts.clone(),
1610 Err(InstructionError::InvalidAccountData),
1611 );
1612
1613 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1615 offset: 0,
1616 bytes: vec![42; 9],
1617 })
1618 .unwrap();
1619 buffer_account
1620 .set_state(&UpgradeableLoaderState::Buffer {
1621 authority_address: Some(buffer_address),
1622 })
1623 .unwrap();
1624 let accounts = process_instruction(
1625 &loader_id,
1626 &instruction,
1627 vec![(buffer_address, buffer_account.clone())],
1628 instruction_accounts.clone(),
1629 Ok(()),
1630 );
1631 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1632 assert_eq!(
1633 state,
1634 UpgradeableLoaderState::Buffer {
1635 authority_address: Some(buffer_address)
1636 }
1637 );
1638 assert_eq!(
1639 &accounts
1640 .first()
1641 .unwrap()
1642 .data()
1643 .get(UpgradeableLoaderState::size_of_buffer_metadata()..)
1644 .unwrap(),
1645 &[42; 9]
1646 );
1647
1648 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1650 offset: 3,
1651 bytes: vec![42; 6],
1652 })
1653 .unwrap();
1654 let mut buffer_account =
1655 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1656 buffer_account
1657 .set_state(&UpgradeableLoaderState::Buffer {
1658 authority_address: Some(buffer_address),
1659 })
1660 .unwrap();
1661 let accounts = process_instruction(
1662 &loader_id,
1663 &instruction,
1664 vec![(buffer_address, buffer_account.clone())],
1665 instruction_accounts.clone(),
1666 Ok(()),
1667 );
1668 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1669 assert_eq!(
1670 state,
1671 UpgradeableLoaderState::Buffer {
1672 authority_address: Some(buffer_address)
1673 }
1674 );
1675 assert_eq!(
1676 &accounts
1677 .first()
1678 .unwrap()
1679 .data()
1680 .get(UpgradeableLoaderState::size_of_buffer_metadata()..)
1681 .unwrap(),
1682 &[0, 0, 0, 42, 42, 42, 42, 42, 42]
1683 );
1684
1685 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1687 offset: 0,
1688 bytes: vec![42; 10],
1689 })
1690 .unwrap();
1691 buffer_account
1692 .set_state(&UpgradeableLoaderState::Buffer {
1693 authority_address: Some(buffer_address),
1694 })
1695 .unwrap();
1696 process_instruction(
1697 &loader_id,
1698 &instruction,
1699 vec![(buffer_address, buffer_account.clone())],
1700 instruction_accounts.clone(),
1701 Err(InstructionError::AccountDataTooSmall),
1702 );
1703
1704 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1706 offset: 1,
1707 bytes: vec![42; 9],
1708 })
1709 .unwrap();
1710 buffer_account
1711 .set_state(&UpgradeableLoaderState::Buffer {
1712 authority_address: Some(buffer_address),
1713 })
1714 .unwrap();
1715 process_instruction(
1716 &loader_id,
1717 &instruction,
1718 vec![(buffer_address, buffer_account.clone())],
1719 instruction_accounts.clone(),
1720 Err(InstructionError::AccountDataTooSmall),
1721 );
1722
1723 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1725 offset: 0,
1726 bytes: vec![42; 9],
1727 })
1728 .unwrap();
1729 buffer_account
1730 .set_state(&UpgradeableLoaderState::Buffer {
1731 authority_address: Some(buffer_address),
1732 })
1733 .unwrap();
1734 process_instruction(
1735 &loader_id,
1736 &instruction,
1737 vec![(buffer_address, buffer_account.clone())],
1738 vec![
1739 AccountMeta {
1740 pubkey: buffer_address,
1741 is_signer: false,
1742 is_writable: false,
1743 },
1744 AccountMeta {
1745 pubkey: buffer_address,
1746 is_signer: false,
1747 is_writable: false,
1748 },
1749 ],
1750 Err(InstructionError::MissingRequiredSignature),
1751 );
1752
1753 let authority_address = Pubkey::new_unique();
1755 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1756 offset: 1,
1757 bytes: vec![42; 9],
1758 })
1759 .unwrap();
1760 buffer_account
1761 .set_state(&UpgradeableLoaderState::Buffer {
1762 authority_address: Some(buffer_address),
1763 })
1764 .unwrap();
1765 process_instruction(
1766 &loader_id,
1767 &instruction,
1768 vec![
1769 (buffer_address, buffer_account.clone()),
1770 (authority_address, buffer_account.clone()),
1771 ],
1772 vec![
1773 AccountMeta {
1774 pubkey: buffer_address,
1775 is_signer: false,
1776 is_writable: false,
1777 },
1778 AccountMeta {
1779 pubkey: authority_address,
1780 is_signer: false,
1781 is_writable: false,
1782 },
1783 ],
1784 Err(InstructionError::IncorrectAuthority),
1785 );
1786
1787 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1789 offset: 1,
1790 bytes: vec![42; 9],
1791 })
1792 .unwrap();
1793 buffer_account
1794 .set_state(&UpgradeableLoaderState::Buffer {
1795 authority_address: None,
1796 })
1797 .unwrap();
1798 process_instruction(
1799 &loader_id,
1800 &instruction,
1801 vec![(buffer_address, buffer_account.clone())],
1802 instruction_accounts,
1803 Err(InstructionError::Immutable),
1804 );
1805 }
1806
1807 fn truncate_data(account: &mut AccountSharedData, len: usize) {
1808 let mut data = account.data().to_vec();
1809 data.truncate(len);
1810 account.set_data_from_slice(&data);
1811 }
1812
1813 #[test]
1814 fn test_write_instruction_matches_sdk() {
1815 let instruction = UpgradeableLoaderInstruction::Write {
1816 offset: 7,
1817 bytes: vec![1, 2, 3],
1818 };
1819 let UpgradeableLoaderInstruction::Write { offset, bytes } = &instruction else {
1822 unreachable!()
1823 };
1824 let serialized = bincode::serialize(&instruction).unwrap();
1825 assert!(serialized.starts_with(&WRITE_INSTRUCTION_TAG));
1826 assert_eq!(
1827 parse_write_instruction(&serialized).unwrap(),
1828 (*offset, bytes.as_slice())
1829 );
1830 }
1831
1832 #[test]
1833 fn test_bpf_loader_upgradeable_write_parsing() {
1834 let loader_id = bpf_loader_upgradeable::id();
1835 let buffer_address = Pubkey::new_unique();
1836 let max_bytes = solana_packet::PACKET_DATA_SIZE - WRITE_INSTRUCTION_HEADER_LEN;
1837 let mut buffer_account = AccountSharedData::new(
1838 1,
1839 UpgradeableLoaderState::size_of_buffer(max_bytes + 1),
1840 &loader_id,
1841 );
1842 buffer_account
1843 .set_state(&UpgradeableLoaderState::Buffer {
1844 authority_address: Some(buffer_address),
1845 })
1846 .unwrap();
1847 let instruction_accounts = vec![
1848 AccountMeta {
1849 pubkey: buffer_address,
1850 is_signer: false,
1851 is_writable: true,
1852 },
1853 AccountMeta {
1854 pubkey: buffer_address,
1855 is_signer: true,
1856 is_writable: false,
1857 },
1858 ];
1859 let write = |declared_len: u64, present: usize, trailing: usize| {
1862 let mut data = WRITE_INSTRUCTION_TAG.to_vec();
1863 data.extend_from_slice(&0u32.to_le_bytes());
1864 data.extend_from_slice(&declared_len.to_le_bytes());
1865 data.extend(std::iter::repeat_n(42u8, present));
1866 data.extend(std::iter::repeat_n(7u8, trailing));
1867 data
1868 };
1869
1870 let accounts = process_instruction(
1872 &loader_id,
1873 &write(9, 9, 100),
1874 vec![(buffer_address, buffer_account.clone())],
1875 instruction_accounts.clone(),
1876 Ok(()),
1877 );
1878 let (written, untouched) = accounts
1879 .first()
1880 .unwrap()
1881 .data()
1882 .get(UpgradeableLoaderState::size_of_buffer_metadata()..)
1883 .unwrap()
1884 .split_at(9);
1885 assert_eq!(written, &[42; 9]);
1886 assert!(untouched.iter().all(|byte| *byte == 0));
1887
1888 process_instruction(
1890 &loader_id,
1891 &write(max_bytes as u64, max_bytes, 0),
1892 vec![(buffer_address, buffer_account.clone())],
1893 instruction_accounts.clone(),
1894 Ok(()),
1895 );
1896
1897 process_instruction(
1899 &loader_id,
1900 &write(max_bytes as u64 + 1, max_bytes + 1, 0),
1901 vec![(buffer_address, buffer_account.clone())],
1902 instruction_accounts.clone(),
1903 Err(InstructionError::InvalidInstructionData),
1904 );
1905
1906 process_instruction(
1908 &loader_id,
1909 &write(600, 512, 0),
1910 vec![(buffer_address, buffer_account.clone())],
1911 instruction_accounts.clone(),
1912 Err(InstructionError::InvalidInstructionData),
1913 );
1914
1915 process_instruction(
1917 &loader_id,
1918 &write(u64::MAX, 512, 0),
1919 vec![(buffer_address, buffer_account.clone())],
1920 instruction_accounts.clone(),
1921 Err(InstructionError::InvalidInstructionData),
1922 );
1923
1924 process_instruction(
1926 &loader_id,
1927 write(0, 0, 0)
1928 .get(..WRITE_INSTRUCTION_HEADER_LEN - 1)
1929 .unwrap(),
1930 vec![(buffer_address, buffer_account)],
1931 instruction_accounts,
1932 Err(InstructionError::InvalidInstructionData),
1933 );
1934 }
1935
1936 #[test_case(true; "simd_0433_enabled")]
1937 #[test_case(false; "simd_0433_disabled")]
1938 fn test_bpf_loader_upgradeable_upgrade(set_programdata_to_elf_length: bool) {
1939 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
1940 let mut elf_orig = Vec::new();
1941 file.read_to_end(&mut elf_orig).unwrap();
1942 let mut file = File::open("test_elfs/out/sbpfv3_return_err.so").expect("file open failed");
1943 let mut elf_new = Vec::new();
1944 file.read_to_end(&mut elf_new).unwrap();
1945 assert_ne!(elf_orig.len(), elf_new.len());
1946 const SLOT: u64 = 42;
1947 let buffer_address = Pubkey::new_unique();
1948 let upgrade_authority_address = Pubkey::new_unique();
1949
1950 fn get_accounts(
1951 buffer_address: &Pubkey,
1952 buffer_authority: &Pubkey,
1953 upgrade_authority_address: &Pubkey,
1954 elf_orig: &[u8],
1955 elf_new: &[u8],
1956 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
1957 let loader_id = bpf_loader_upgradeable::id();
1958 let program_address = Pubkey::new_unique();
1959 let spill_address = Pubkey::new_unique();
1960 let rent = Rent::default();
1961 let min_program_balance =
1962 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_program()));
1963 let min_programdata_balance = 1.max(rent.minimum_balance(
1964 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len())),
1965 ));
1966 let (programdata_address, _) =
1967 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
1968 let mut buffer_account = AccountSharedData::new(
1969 1,
1970 UpgradeableLoaderState::size_of_buffer(elf_new.len()),
1971 &bpf_loader_upgradeable::id(),
1972 );
1973 buffer_account
1974 .set_state(&UpgradeableLoaderState::Buffer {
1975 authority_address: Some(*buffer_authority),
1976 })
1977 .unwrap();
1978 buffer_account
1979 .data_as_mut_slice()
1980 .get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
1981 .unwrap()
1982 .copy_from_slice(elf_new);
1983 let mut programdata_account = AccountSharedData::new(
1984 min_programdata_balance,
1985 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len())),
1986 &bpf_loader_upgradeable::id(),
1987 );
1988 programdata_account
1989 .set_state(&UpgradeableLoaderState::ProgramData {
1990 slot: SLOT,
1991 upgrade_authority_address: Some(*upgrade_authority_address),
1992 })
1993 .unwrap();
1994 let mut program_account = AccountSharedData::new(
1995 min_program_balance,
1996 UpgradeableLoaderState::size_of_program(),
1997 &bpf_loader_upgradeable::id(),
1998 );
1999 program_account.set_executable(true);
2000 program_account
2001 .set_state(&UpgradeableLoaderState::Program {
2002 programdata_address,
2003 })
2004 .unwrap();
2005 let spill_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
2006 let rent_account = create_sysvar_account(&rent);
2007 let clock_account = create_sysvar_account(&Clock {
2008 slot: SLOT.saturating_add(1),
2009 ..Clock::default()
2010 });
2011 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
2012 let transaction_accounts = vec![
2013 (programdata_address, programdata_account),
2014 (program_address, program_account),
2015 (*buffer_address, buffer_account),
2016 (spill_address, spill_account),
2017 (sysvar::rent::id(), rent_account),
2018 (sysvar::clock::id(), clock_account),
2019 (*upgrade_authority_address, upgrade_authority_account),
2020 ];
2021 let instruction_accounts = vec![
2022 AccountMeta {
2023 pubkey: programdata_address,
2024 is_signer: false,
2025 is_writable: true,
2026 },
2027 AccountMeta {
2028 pubkey: program_address,
2029 is_signer: false,
2030 is_writable: true,
2031 },
2032 AccountMeta {
2033 pubkey: *buffer_address,
2034 is_signer: false,
2035 is_writable: true,
2036 },
2037 AccountMeta {
2038 pubkey: spill_address,
2039 is_signer: false,
2040 is_writable: true,
2041 },
2042 AccountMeta {
2043 pubkey: sysvar::rent::id(),
2044 is_signer: false,
2045 is_writable: false,
2046 },
2047 AccountMeta {
2048 pubkey: sysvar::clock::id(),
2049 is_signer: false,
2050 is_writable: false,
2051 },
2052 AccountMeta {
2053 pubkey: *upgrade_authority_address,
2054 is_signer: true,
2055 is_writable: false,
2056 },
2057 ];
2058 (transaction_accounts, instruction_accounts)
2059 }
2060
2061 let process_instruction =
2062 |transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
2063 instruction_accounts: Vec<AccountMeta>,
2064 expected_result: Result<(), InstructionError>| {
2065 let instruction_data =
2066 bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
2067 process_instruction_with_setup(
2068 &bpf_loader_upgradeable::id(),
2069 &instruction_data,
2070 transaction_accounts,
2071 instruction_accounts,
2072 LoaderV3Features {
2073 set_programdata_to_elf_length,
2074 },
2075 expected_result,
2076 |_invoke_context| {},
2077 )
2078 };
2079
2080 let (transaction_accounts, instruction_accounts) = get_accounts(
2082 &buffer_address,
2083 &upgrade_authority_address,
2084 &upgrade_authority_address,
2085 &elf_orig,
2086 &elf_new,
2087 );
2088 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2089 let starting_programdata_len =
2090 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len()));
2091 let starting_programdata_balance =
2092 Rent::default().minimum_balance(starting_programdata_len);
2093 let expected_programdata_len = if set_programdata_to_elf_length {
2094 UpgradeableLoaderState::size_of_programdata(elf_new.len())
2095 } else {
2096 starting_programdata_len
2097 };
2098 let expected_programdata_balance =
2099 Rent::default().minimum_balance(expected_programdata_len);
2100 assert_eq!(
2101 expected_programdata_len,
2102 accounts.first().unwrap().data().len()
2103 );
2104 assert_eq!(
2105 expected_programdata_balance,
2106 accounts.first().unwrap().lamports()
2107 );
2108 assert_eq!(0, accounts.get(2).unwrap().lamports());
2109 assert_eq!(
2111 starting_programdata_balance
2112 .saturating_sub(expected_programdata_balance)
2113 .saturating_add(1),
2114 accounts.get(3).unwrap().lamports()
2115 );
2116 assert_eq!(
2117 UpgradeableLoaderState::size_of_buffer(0),
2118 accounts.get(2).unwrap().data().len()
2119 );
2120 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
2121 assert_eq!(
2122 state,
2123 UpgradeableLoaderState::ProgramData {
2124 slot: SLOT.saturating_add(1),
2125 upgrade_authority_address: Some(upgrade_authority_address)
2126 }
2127 );
2128 for (i, byte) in accounts
2129 .first()
2130 .unwrap()
2131 .data()
2132 .get(
2133 UpgradeableLoaderState::size_of_programdata_metadata()
2134 ..UpgradeableLoaderState::size_of_programdata(elf_new.len()),
2135 )
2136 .unwrap()
2137 .iter()
2138 .enumerate()
2139 {
2140 assert_eq!(*elf_new.get(i).unwrap(), *byte);
2141 }
2142
2143 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2145 &buffer_address,
2146 &upgrade_authority_address,
2147 &upgrade_authority_address,
2148 &elf_orig,
2149 &elf_new,
2150 );
2151 transaction_accounts
2152 .get_mut(0)
2153 .unwrap()
2154 .1
2155 .set_state(&UpgradeableLoaderState::ProgramData {
2156 slot: SLOT,
2157 upgrade_authority_address: None,
2158 })
2159 .unwrap();
2160 process_instruction(
2161 transaction_accounts,
2162 instruction_accounts,
2163 Err(InstructionError::Immutable),
2164 );
2165
2166 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2168 &buffer_address,
2169 &upgrade_authority_address,
2170 &upgrade_authority_address,
2171 &elf_orig,
2172 &elf_new,
2173 );
2174 let invalid_upgrade_authority_address = Pubkey::new_unique();
2175 transaction_accounts.get_mut(6).unwrap().0 = invalid_upgrade_authority_address;
2176 instruction_accounts.get_mut(6).unwrap().pubkey = invalid_upgrade_authority_address;
2177 process_instruction(
2178 transaction_accounts,
2179 instruction_accounts,
2180 Err(InstructionError::IncorrectAuthority),
2181 );
2182
2183 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2185 &buffer_address,
2186 &upgrade_authority_address,
2187 &upgrade_authority_address,
2188 &elf_orig,
2189 &elf_new,
2190 );
2191 instruction_accounts.get_mut(6).unwrap().is_signer = false;
2192 process_instruction(
2193 transaction_accounts,
2194 instruction_accounts,
2195 Err(InstructionError::MissingRequiredSignature),
2196 );
2197
2198 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2200 &buffer_address,
2201 &upgrade_authority_address,
2202 &upgrade_authority_address,
2203 &elf_orig,
2204 &elf_new,
2205 );
2206 *instruction_accounts.get_mut(3).unwrap() = instruction_accounts.get(2).unwrap().clone();
2207 process_instruction(
2208 transaction_accounts,
2209 instruction_accounts,
2210 Err(InstructionError::AccountBorrowFailed),
2211 );
2212
2213 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2215 &buffer_address,
2216 &upgrade_authority_address,
2217 &upgrade_authority_address,
2218 &elf_orig,
2219 &elf_new,
2220 );
2221 *instruction_accounts.get_mut(3).unwrap() = instruction_accounts.first().unwrap().clone();
2222 process_instruction(
2223 transaction_accounts,
2224 instruction_accounts,
2225 Err(InstructionError::AccountBorrowFailed),
2226 );
2227
2228 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2230 &buffer_address,
2231 &upgrade_authority_address,
2232 &upgrade_authority_address,
2233 &elf_orig,
2234 &elf_new,
2235 );
2236 *instruction_accounts.get_mut(1).unwrap() = instruction_accounts.get(2).unwrap().clone();
2237 let instruction_data = bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
2238
2239 process_instruction_with_setup(
2240 &bpf_loader_upgradeable::id(),
2241 &instruction_data,
2242 transaction_accounts.clone(),
2243 instruction_accounts.clone(),
2244 LoaderV3Features {
2245 set_programdata_to_elf_length,
2246 },
2247 Err(InstructionError::InvalidAccountData),
2248 |invoke_context| {
2249 test_utils::load_all_invoked_programs(invoke_context);
2250 },
2251 );
2252 process_instruction(
2253 transaction_accounts.clone(),
2254 instruction_accounts.clone(),
2255 Err(InstructionError::InvalidAccountData),
2256 );
2257
2258 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2260 &buffer_address,
2261 &upgrade_authority_address,
2262 &upgrade_authority_address,
2263 &elf_orig,
2264 &elf_new,
2265 );
2266 transaction_accounts
2267 .get_mut(1)
2268 .unwrap()
2269 .1
2270 .set_owner(Pubkey::new_unique());
2271 process_instruction(
2272 transaction_accounts,
2273 instruction_accounts,
2274 Err(InstructionError::IncorrectProgramId),
2275 );
2276
2277 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2279 &buffer_address,
2280 &upgrade_authority_address,
2281 &upgrade_authority_address,
2282 &elf_orig,
2283 &elf_new,
2284 );
2285 instruction_accounts.get_mut(1).unwrap().is_writable = false;
2286 process_instruction(
2287 transaction_accounts,
2288 instruction_accounts,
2289 Err(InstructionError::InvalidArgument),
2290 );
2291
2292 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2294 &buffer_address,
2295 &upgrade_authority_address,
2296 &upgrade_authority_address,
2297 &elf_orig,
2298 &elf_new,
2299 );
2300 transaction_accounts
2301 .get_mut(1)
2302 .unwrap()
2303 .1
2304 .set_state(&UpgradeableLoaderState::Uninitialized)
2305 .unwrap();
2306 process_instruction(
2307 transaction_accounts,
2308 instruction_accounts,
2309 Err(InstructionError::InvalidAccountData),
2310 );
2311
2312 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2314 &buffer_address,
2315 &upgrade_authority_address,
2316 &upgrade_authority_address,
2317 &elf_orig,
2318 &elf_new,
2319 );
2320 let invalid_programdata_address = Pubkey::new_unique();
2321 transaction_accounts.get_mut(0).unwrap().0 = invalid_programdata_address;
2322 instruction_accounts.get_mut(0).unwrap().pubkey = invalid_programdata_address;
2323 process_instruction(
2324 transaction_accounts,
2325 instruction_accounts,
2326 Err(InstructionError::InvalidArgument),
2327 );
2328
2329 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2331 &buffer_address,
2332 &upgrade_authority_address,
2333 &upgrade_authority_address,
2334 &elf_orig,
2335 &elf_new,
2336 );
2337 transaction_accounts
2338 .get_mut(2)
2339 .unwrap()
2340 .1
2341 .set_state(&UpgradeableLoaderState::Uninitialized)
2342 .unwrap();
2343 process_instruction(
2344 transaction_accounts,
2345 instruction_accounts,
2346 Err(InstructionError::InvalidArgument),
2347 );
2348
2349 for buffer_balance in [0, 1_000_000, 15 * 1_000_000_000] {
2351 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2352 &buffer_address,
2353 &upgrade_authority_address,
2354 &upgrade_authority_address,
2355 &elf_orig,
2356 &elf_new,
2357 );
2358 transaction_accounts
2359 .get_mut(2)
2360 .unwrap()
2361 .1
2362 .set_lamports(buffer_balance);
2363 instruction_accounts.get_mut(2).unwrap().is_writable = false;
2364 process_instruction(
2365 transaction_accounts,
2366 instruction_accounts,
2367 Err(InstructionError::InvalidArgument),
2368 );
2369 }
2370
2371 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2377 &buffer_address,
2378 &upgrade_authority_address,
2379 &upgrade_authority_address,
2380 &elf_orig,
2381 &elf_new,
2382 );
2383 {
2384 let required_rent = |elf_len| {
2386 Rent::default()
2387 .minimum_balance(UpgradeableLoaderState::size_of_programdata(elf_len))
2388 };
2389 let rent_orig = required_rent(elf_orig.len());
2390 let rent_new = required_rent(elf_new.len());
2391 let programdata = &mut transaction_accounts.first_mut().unwrap().1;
2392 programdata.set_lamports(rent_orig);
2393 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2394 buffer.set_owner(Pubkey::new_unique());
2395 buffer.set_lamports(rent_new);
2396 }
2397 process_instruction(
2398 transaction_accounts,
2399 instruction_accounts,
2400 Err(InstructionError::IncorrectProgramId),
2401 );
2402
2403 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2408 &buffer_address,
2409 &upgrade_authority_address,
2410 &upgrade_authority_address,
2411 &elf_orig,
2412 &elf_new,
2413 );
2414 {
2415 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2417 buffer.set_owner(Pubkey::new_unique());
2418 buffer.set_lamports(0);
2419 }
2420 process_instruction(
2421 transaction_accounts,
2422 instruction_accounts,
2423 Err(InstructionError::IncorrectProgramId),
2424 );
2425
2426 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2432 &buffer_address,
2433 &upgrade_authority_address,
2434 &upgrade_authority_address,
2435 &elf_orig,
2436 &elf_new,
2437 );
2438 {
2439 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2441 buffer.set_owner(Pubkey::new_unique());
2442 buffer.set_lamports(0);
2443 truncate_data(buffer, UpgradeableLoaderState::size_of_buffer(0));
2444 }
2445 process_instruction(
2446 transaction_accounts,
2447 instruction_accounts,
2448 Err(InstructionError::IncorrectProgramId),
2449 );
2450
2451 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2453 &buffer_address,
2454 &upgrade_authority_address,
2455 &upgrade_authority_address,
2456 &elf_orig,
2457 &elf_new,
2458 );
2459 transaction_accounts.get_mut(2).unwrap().1 = AccountSharedData::new(
2460 1,
2461 UpgradeableLoaderState::size_of_buffer(
2462 elf_orig.len().max(elf_new.len()).saturating_add(1),
2463 ),
2464 &bpf_loader_upgradeable::id(),
2465 );
2466 transaction_accounts
2467 .get_mut(2)
2468 .unwrap()
2469 .1
2470 .set_state(&UpgradeableLoaderState::Buffer {
2471 authority_address: Some(upgrade_authority_address),
2472 })
2473 .unwrap();
2474 process_instruction(
2475 transaction_accounts,
2476 instruction_accounts,
2477 if set_programdata_to_elf_length {
2478 Err(InstructionError::InsufficientFunds)
2479 } else {
2480 Err(InstructionError::AccountDataTooSmall)
2481 },
2482 );
2483
2484 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2486 &buffer_address,
2487 &upgrade_authority_address,
2488 &upgrade_authority_address,
2489 &elf_orig,
2490 &elf_new,
2491 );
2492 transaction_accounts
2493 .get_mut(2)
2494 .unwrap()
2495 .1
2496 .set_state(&UpgradeableLoaderState::Buffer {
2497 authority_address: Some(upgrade_authority_address),
2498 })
2499 .unwrap();
2500 truncate_data(&mut transaction_accounts.get_mut(2).unwrap().1, 5);
2501 process_instruction(
2502 transaction_accounts,
2503 instruction_accounts,
2504 Err(InstructionError::InvalidAccountData),
2505 );
2506
2507 let (transaction_accounts, instruction_accounts) = get_accounts(
2509 &buffer_address,
2510 &buffer_address,
2511 &upgrade_authority_address,
2512 &elf_orig,
2513 &elf_new,
2514 );
2515 process_instruction(
2516 transaction_accounts,
2517 instruction_accounts,
2518 Err(InstructionError::IncorrectAuthority),
2519 );
2520
2521 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2523 &buffer_address,
2524 &buffer_address,
2525 &upgrade_authority_address,
2526 &elf_orig,
2527 &elf_new,
2528 );
2529 transaction_accounts
2530 .get_mut(2)
2531 .unwrap()
2532 .1
2533 .set_state(&UpgradeableLoaderState::Buffer {
2534 authority_address: None,
2535 })
2536 .unwrap();
2537 process_instruction(
2538 transaction_accounts,
2539 instruction_accounts,
2540 Err(InstructionError::IncorrectAuthority),
2541 );
2542
2543 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2545 &buffer_address,
2546 &buffer_address,
2547 &upgrade_authority_address,
2548 &elf_orig,
2549 &elf_new,
2550 );
2551 transaction_accounts
2552 .get_mut(0)
2553 .unwrap()
2554 .1
2555 .set_state(&UpgradeableLoaderState::ProgramData {
2556 slot: SLOT,
2557 upgrade_authority_address: None,
2558 })
2559 .unwrap();
2560 transaction_accounts
2561 .get_mut(2)
2562 .unwrap()
2563 .1
2564 .set_state(&UpgradeableLoaderState::Buffer {
2565 authority_address: None,
2566 })
2567 .unwrap();
2568 process_instruction(
2569 transaction_accounts,
2570 instruction_accounts,
2571 Err(InstructionError::IncorrectAuthority),
2572 );
2573
2574 let mut file =
2576 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
2577 let mut elf_new = Vec::new();
2578 file.read_to_end(&mut elf_new).unwrap();
2579 let (transaction_accounts, instruction_accounts) = get_accounts(
2580 &buffer_address,
2581 &upgrade_authority_address,
2582 &upgrade_authority_address,
2583 &elf_orig,
2584 &elf_new,
2585 );
2586 process_instruction(
2587 transaction_accounts,
2588 instruction_accounts,
2589 Err(InstructionError::InvalidAccountData),
2590 );
2591 }
2592
2593 #[test]
2594 fn test_bpf_loader_upgradeable_upgrade_simd_0433() {
2595 let mut file = File::open("test_elfs/out/sbpfv3_return_err.so").expect("file open failed");
2596 let mut elf_small = Vec::new();
2597 file.read_to_end(&mut elf_small).unwrap();
2598 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
2599 let mut elf_large = Vec::new();
2600 file.read_to_end(&mut elf_large).unwrap();
2601 assert!(elf_small.len() < elf_large.len());
2602 const SLOT: u64 = 42;
2603 let upgrade_authority_address = Pubkey::new_unique();
2604
2605 fn get_accounts(
2606 upgrade_authority_address: &Pubkey,
2607 elf_orig: &[u8],
2608 elf_new: &[u8],
2609 programdata_len: usize,
2610 programdata_lamports: u64,
2611 buffer_len: usize,
2612 buffer_lamports: u64,
2613 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
2614 assert!(programdata_len >= UpgradeableLoaderState::size_of_programdata(elf_orig.len()));
2615 assert!(buffer_len >= UpgradeableLoaderState::size_of_buffer(elf_new.len()));
2616 let loader_id = bpf_loader_upgradeable::id();
2617 let program_address = Pubkey::new_unique();
2618 let buffer_address = Pubkey::new_unique();
2619 let spill_address = Pubkey::new_unique();
2620 let rent = Rent::default();
2621 let (programdata_address, _) =
2622 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
2623
2624 let mut buffer_account =
2625 AccountSharedData::new(buffer_lamports, buffer_len, &loader_id);
2626 buffer_account
2627 .set_state(&UpgradeableLoaderState::Buffer {
2628 authority_address: Some(*upgrade_authority_address),
2629 })
2630 .unwrap();
2631 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
2632 buffer_account
2633 .data_as_mut_slice()
2634 .get_mut(buffer_data_offset..buffer_data_offset.saturating_add(elf_new.len()))
2635 .unwrap()
2636 .copy_from_slice(elf_new);
2637
2638 let mut programdata_account =
2639 AccountSharedData::new(programdata_lamports, programdata_len, &loader_id);
2640 programdata_account
2641 .set_state(&UpgradeableLoaderState::ProgramData {
2642 slot: SLOT,
2643 upgrade_authority_address: Some(*upgrade_authority_address),
2644 })
2645 .unwrap();
2646 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
2647 programdata_account
2648 .data_as_mut_slice()
2649 .get_mut(
2650 programdata_data_offset..programdata_data_offset.saturating_add(elf_orig.len()),
2651 )
2652 .unwrap()
2653 .copy_from_slice(elf_orig);
2654
2655 let mut program_account = AccountSharedData::new(
2656 rent.minimum_balance(UpgradeableLoaderState::size_of_program()),
2657 UpgradeableLoaderState::size_of_program(),
2658 &loader_id,
2659 );
2660 program_account.set_executable(true);
2661 program_account
2662 .set_state(&UpgradeableLoaderState::Program {
2663 programdata_address,
2664 })
2665 .unwrap();
2666
2667 let spill_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
2668 let rent_account = create_sysvar_account(&rent);
2669 let clock_account = create_sysvar_account(&Clock {
2670 slot: SLOT.saturating_add(1),
2671 ..Clock::default()
2672 });
2673 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
2674 let transaction_accounts = vec![
2675 (programdata_address, programdata_account),
2676 (program_address, program_account),
2677 (buffer_address, buffer_account),
2678 (spill_address, spill_account),
2679 (sysvar::rent::id(), rent_account),
2680 (sysvar::clock::id(), clock_account),
2681 (*upgrade_authority_address, upgrade_authority_account),
2682 ];
2683 let instruction_accounts = vec![
2684 AccountMeta {
2685 pubkey: programdata_address,
2686 is_signer: false,
2687 is_writable: true,
2688 },
2689 AccountMeta {
2690 pubkey: program_address,
2691 is_signer: false,
2692 is_writable: true,
2693 },
2694 AccountMeta {
2695 pubkey: buffer_address,
2696 is_signer: false,
2697 is_writable: true,
2698 },
2699 AccountMeta {
2700 pubkey: spill_address,
2701 is_signer: false,
2702 is_writable: true,
2703 },
2704 AccountMeta {
2705 pubkey: sysvar::rent::id(),
2706 is_signer: false,
2707 is_writable: false,
2708 },
2709 AccountMeta {
2710 pubkey: sysvar::clock::id(),
2711 is_signer: false,
2712 is_writable: false,
2713 },
2714 AccountMeta {
2715 pubkey: *upgrade_authority_address,
2716 is_signer: true,
2717 is_writable: false,
2718 },
2719 ];
2720 (transaction_accounts, instruction_accounts)
2721 }
2722
2723 let process_instruction =
2724 |transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
2725 instruction_accounts: Vec<AccountMeta>,
2726 expected_result: Result<(), InstructionError>| {
2727 let instruction_data =
2728 bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
2729 process_instruction_with_setup(
2730 &bpf_loader_upgradeable::id(),
2731 &instruction_data,
2732 transaction_accounts,
2733 instruction_accounts,
2734 LoaderV3Features {
2735 set_programdata_to_elf_length: true,
2736 },
2737 expected_result,
2738 |_invoke_context| {},
2739 )
2740 };
2741
2742 let rent = Rent::default();
2743 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
2744 let small_len = UpgradeableLoaderState::size_of_programdata(elf_small.len());
2745 let large_len = UpgradeableLoaderState::size_of_programdata(elf_large.len());
2746 let small_balance = rent.minimum_balance(small_len);
2747 let large_balance = rent.minimum_balance(large_len);
2748
2749 let assert_upgraded =
2750 |accounts: &[AccountSharedData], elf_new: &[u8], expected_len: usize| {
2751 let programdata = accounts.first().unwrap();
2752 assert_eq!(expected_len, programdata.data().len());
2754 assert_eq!(rent.minimum_balance(expected_len), programdata.lamports());
2756 assert_eq!(
2758 elf_new,
2759 programdata
2760 .data()
2761 .get(
2762 programdata_data_offset
2763 ..programdata_data_offset.saturating_add(elf_new.len())
2764 )
2765 .unwrap()
2766 );
2767 let state: UpgradeableLoaderState = programdata.state().unwrap();
2769 assert_eq!(
2770 UpgradeableLoaderState::ProgramData {
2771 slot: SLOT.saturating_add(1),
2772 upgrade_authority_address: Some(upgrade_authority_address),
2773 },
2774 state
2775 );
2776 let buffer = accounts.get(2).unwrap();
2778 assert_eq!(0, buffer.lamports());
2779 assert_eq!(
2780 UpgradeableLoaderState::size_of_buffer(0),
2781 buffer.data().len()
2782 );
2783 };
2784
2785 let (transaction_accounts, instruction_accounts) = get_accounts(
2787 &upgrade_authority_address,
2788 &elf_large,
2789 &elf_small,
2790 large_len,
2791 large_balance,
2792 UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2793 1,
2794 );
2795 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2796 assert_upgraded(&accounts, &elf_small, small_len);
2797 assert_eq!(
2798 large_balance
2799 .saturating_sub(small_balance)
2800 .saturating_add(1),
2801 accounts.get(3).unwrap().lamports()
2802 );
2803
2804 let extended_len = large_len.saturating_add(4096);
2806 let extended_balance = rent.minimum_balance(extended_len);
2807 let (transaction_accounts, instruction_accounts) = get_accounts(
2808 &upgrade_authority_address,
2809 &elf_large,
2810 &elf_small,
2811 extended_len,
2812 extended_balance,
2813 UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2814 1,
2815 );
2816 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2817 assert_upgraded(&accounts, &elf_small, small_len);
2818 assert_eq!(
2819 extended_balance
2820 .saturating_sub(small_balance)
2821 .saturating_add(1),
2822 accounts.get(3).unwrap().lamports()
2823 );
2824
2825 let extended_len = large_len.saturating_add(4096);
2830 let extended_balance = rent.minimum_balance(extended_len);
2831 let (transaction_accounts, instruction_accounts) = get_accounts(
2832 &upgrade_authority_address,
2833 &elf_small,
2834 &elf_large,
2835 extended_len,
2836 extended_balance,
2837 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2838 1,
2839 );
2840 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2841 assert_upgraded(&accounts, &elf_large, large_len);
2842 assert!(small_len < large_len && large_len < extended_len);
2843 assert_eq!(
2844 extended_balance
2845 .saturating_sub(large_balance)
2846 .saturating_add(1),
2847 accounts.get(3).unwrap().lamports()
2848 );
2849
2850 let padded_buffer_len =
2852 UpgradeableLoaderState::size_of_buffer(elf_small.len()).saturating_add(32);
2853 let padded_len = small_len.saturating_add(32);
2854 let padded_balance = rent.minimum_balance(padded_len);
2855 assert!(padded_len < large_len);
2856 let (transaction_accounts, instruction_accounts) = get_accounts(
2857 &upgrade_authority_address,
2858 &elf_large,
2859 &elf_small,
2860 large_len,
2861 large_balance,
2862 padded_buffer_len,
2863 1,
2864 );
2865 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2866 assert_upgraded(&accounts, &elf_small, padded_len);
2867 assert!(
2869 accounts
2870 .first()
2871 .unwrap()
2872 .data()
2873 .get(programdata_data_offset.saturating_add(elf_small.len())..)
2874 .unwrap()
2875 .iter()
2876 .all(|byte| *byte == 0)
2877 );
2878 assert_eq!(
2879 large_balance
2880 .saturating_sub(padded_balance)
2881 .saturating_add(1),
2882 accounts.get(3).unwrap().lamports()
2883 );
2884
2885 let (transaction_accounts, instruction_accounts) = get_accounts(
2887 &upgrade_authority_address,
2888 &elf_large,
2889 &elf_small,
2890 large_len,
2891 small_balance, UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2893 0,
2894 );
2895 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2896 assert_upgraded(&accounts, &elf_small, small_len);
2897 assert_eq!(0, accounts.get(3).unwrap().lamports());
2898
2899 let (transaction_accounts, instruction_accounts) = get_accounts(
2902 &upgrade_authority_address,
2903 &elf_large,
2904 &elf_small,
2905 large_len,
2906 small_balance.saturating_sub(1),
2907 UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2908 0,
2909 );
2910 process_instruction(
2911 transaction_accounts,
2912 instruction_accounts,
2913 Err(InstructionError::InsufficientFunds),
2914 );
2915
2916 let (transaction_accounts, instruction_accounts) = get_accounts(
2918 &upgrade_authority_address,
2919 &elf_small,
2920 &elf_large,
2921 small_len,
2922 small_balance,
2923 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2924 large_balance,
2925 );
2926 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2927 assert_upgraded(&accounts, &elf_large, large_len);
2928 assert_eq!(small_balance, accounts.get(3).unwrap().lamports());
2931
2932 let extended_len = small_len.saturating_add(50);
2934 let extended_balance = rent.minimum_balance(extended_len);
2935 assert!(extended_len < large_len);
2936 let (transaction_accounts, instruction_accounts) = get_accounts(
2937 &upgrade_authority_address,
2938 &elf_small,
2939 &elf_large,
2940 extended_len,
2941 extended_balance,
2942 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2943 large_balance,
2944 );
2945 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2946 assert_upgraded(&accounts, &elf_large, large_len);
2947 assert_eq!(extended_balance, accounts.get(3).unwrap().lamports());
2951
2952 let padded_buffer_len =
2954 UpgradeableLoaderState::size_of_buffer(elf_large.len()).saturating_add(64);
2955 let padded_len = large_len.saturating_add(64);
2956 let padded_balance = rent.minimum_balance(padded_len);
2957 let (transaction_accounts, instruction_accounts) = get_accounts(
2958 &upgrade_authority_address,
2959 &elf_small,
2960 &elf_large,
2961 small_len,
2962 padded_balance,
2963 padded_buffer_len,
2964 0,
2965 );
2966 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2967 assert_upgraded(&accounts, &elf_large, padded_len);
2968 assert!(
2969 accounts
2970 .first()
2971 .unwrap()
2972 .data()
2973 .get(programdata_data_offset.saturating_add(elf_large.len())..)
2974 .unwrap()
2975 .iter()
2976 .all(|byte| *byte == 0)
2977 );
2978 assert_eq!(0, accounts.get(3).unwrap().lamports());
2979
2980 let (transaction_accounts, instruction_accounts) = get_accounts(
2982 &upgrade_authority_address,
2983 &elf_small,
2984 &elf_large,
2985 small_len,
2986 large_balance,
2987 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2988 0,
2989 );
2990 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2991 assert_upgraded(&accounts, &elf_large, large_len);
2992 assert_eq!(0, accounts.get(3).unwrap().lamports());
2994
2995 let deficit = large_balance.saturating_sub(small_balance);
2997 let (transaction_accounts, instruction_accounts) = get_accounts(
2998 &upgrade_authority_address,
2999 &elf_small,
3000 &elf_large,
3001 small_len,
3002 small_balance,
3003 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
3004 deficit.saturating_sub(1), );
3006 process_instruction(
3007 transaction_accounts,
3008 instruction_accounts,
3009 Err(InstructionError::InsufficientFunds),
3010 );
3011
3012 let (transaction_accounts, instruction_accounts) = get_accounts(
3014 &upgrade_authority_address,
3015 &elf_large,
3016 &elf_large,
3017 large_len,
3018 large_balance,
3019 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
3020 1,
3021 );
3022 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
3023 assert_upgraded(&accounts, &elf_large, large_len);
3024 assert_eq!(1, accounts.get(3).unwrap().lamports());
3026
3027 let (transaction_accounts, instruction_accounts) = get_accounts(
3029 &upgrade_authority_address,
3030 &elf_large,
3031 &[],
3032 large_len,
3033 large_balance,
3034 UpgradeableLoaderState::size_of_buffer(0),
3035 1,
3036 );
3037 process_instruction(
3038 transaction_accounts,
3039 instruction_accounts,
3040 Err(InstructionError::InvalidAccountData),
3041 );
3042
3043 let oversized_elf_len = (MAX_PERMITTED_DATA_LENGTH as usize)
3045 .saturating_sub(UpgradeableLoaderState::size_of_buffer_metadata());
3046 let mut oversized_elf = elf_large.clone();
3047 oversized_elf.resize(oversized_elf_len, 0);
3048 assert!(
3049 UpgradeableLoaderState::size_of_programdata(oversized_elf.len())
3050 > MAX_PERMITTED_DATA_LENGTH as usize
3051 );
3052 let (transaction_accounts, instruction_accounts) = get_accounts(
3053 &upgrade_authority_address,
3054 &elf_small,
3055 &oversized_elf,
3056 small_len,
3057 u64::MAX / 2,
3058 UpgradeableLoaderState::size_of_buffer(oversized_elf.len()),
3059 0,
3060 );
3061 process_instruction(
3062 transaction_accounts,
3063 instruction_accounts,
3064 Err(InstructionError::InvalidAccountData),
3065 );
3066 }
3067
3068 #[test]
3069 fn test_bpf_loader_upgradeable_deploy_with_max_data_len() {
3070 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
3071 let mut elf = Vec::new();
3072 file.read_to_end(&mut elf).unwrap();
3073 const SLOT: u64 = 42;
3074 let payer_address = Pubkey::new_unique();
3075 let buffer_address = Pubkey::new_unique();
3076 let upgrade_authority_address = Pubkey::new_unique();
3077
3078 fn get_accounts(
3079 payer_address: &Pubkey,
3080 buffer_address: &Pubkey,
3081 buffer_authority: &Pubkey,
3082 upgrade_authority_address: &Pubkey,
3083 elf: &[u8],
3084 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
3085 let loader_id = bpf_loader_upgradeable::id();
3086 let program_address = Pubkey::new_unique();
3087 let rent = Rent::default();
3088 let min_program_balance =
3089 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_program()));
3090 let min_programdata_balance =
3091 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len())));
3092 let (programdata_address, _) =
3093 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
3094 let mut buffer_account = AccountSharedData::new(
3095 1,
3096 UpgradeableLoaderState::size_of_buffer(elf.len()),
3097 &bpf_loader_upgradeable::id(),
3098 );
3099 buffer_account
3100 .set_state(&UpgradeableLoaderState::Buffer {
3101 authority_address: Some(*buffer_authority),
3102 })
3103 .unwrap();
3104 buffer_account
3105 .data_as_mut_slice()
3106 .get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
3107 .unwrap()
3108 .copy_from_slice(elf);
3109 let programdata_account = AccountSharedData::new(0, 0, &system_program::id());
3110 let mut program_account = AccountSharedData::new(
3111 min_program_balance,
3112 UpgradeableLoaderState::size_of_program(),
3113 &bpf_loader_upgradeable::id(),
3114 );
3115 program_account
3116 .set_state(&UpgradeableLoaderState::Uninitialized)
3117 .unwrap();
3118 let payer_account = AccountSharedData::new(
3119 min_programdata_balance.saturating_add(1),
3120 0,
3121 &system_program::id(),
3122 );
3123 let rent_account = create_sysvar_account(&rent);
3124 let clock_account = create_sysvar_account(&Clock {
3125 slot: SLOT,
3126 ..Clock::default()
3127 });
3128 let system_program_account = AccountSharedData::new(0, 0, &native_loader::id());
3129 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3130 let transaction_accounts = vec![
3131 (*payer_address, payer_account),
3132 (programdata_address, programdata_account),
3133 (program_address, program_account),
3134 (*buffer_address, buffer_account),
3135 (sysvar::rent::id(), rent_account),
3136 (sysvar::clock::id(), clock_account),
3137 (system_program::id(), system_program_account),
3138 (*upgrade_authority_address, upgrade_authority_account),
3139 ];
3140 let instruction_accounts = vec![
3141 AccountMeta {
3142 pubkey: *payer_address,
3143 is_signer: true,
3144 is_writable: true,
3145 },
3146 AccountMeta {
3147 pubkey: programdata_address,
3148 is_signer: false,
3149 is_writable: true,
3150 },
3151 AccountMeta {
3152 pubkey: program_address,
3153 is_signer: false,
3154 is_writable: true,
3155 },
3156 AccountMeta {
3157 pubkey: *buffer_address,
3158 is_signer: false,
3159 is_writable: true,
3160 },
3161 AccountMeta {
3162 pubkey: sysvar::rent::id(),
3163 is_signer: false,
3164 is_writable: false,
3165 },
3166 AccountMeta {
3167 pubkey: sysvar::clock::id(),
3168 is_signer: false,
3169 is_writable: false,
3170 },
3171 AccountMeta {
3172 pubkey: system_program::id(),
3173 is_signer: false,
3174 is_writable: false,
3175 },
3176 AccountMeta {
3177 pubkey: *upgrade_authority_address,
3178 is_signer: true,
3179 is_writable: false,
3180 },
3181 ];
3182 (transaction_accounts, instruction_accounts)
3183 }
3184
3185 fn process_instruction(
3186 max_data_len: usize,
3187 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
3188 instruction_accounts: Vec<AccountMeta>,
3189 expected_result: Result<(), InstructionError>,
3190 ) -> Vec<AccountSharedData> {
3191 let instruction_data =
3192 bincode::serialize(&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
3193 max_data_len,
3194 })
3195 .unwrap();
3196 process_instruction_with_setup(
3197 &bpf_loader_upgradeable::id(),
3198 &instruction_data,
3199 transaction_accounts,
3200 instruction_accounts,
3201 LoaderV3Features::all_enabled(),
3202 expected_result,
3203 |invoke_context| {
3204 invoke_context.program_cache_for_tx_batch.replenish(
3206 system_program::id(),
3207 Arc::new(ProgramCacheEntry::new_builtin(
3208 solana_system_program::system_processor::Entrypoint::register,
3209 )),
3210 );
3211 },
3212 )
3213 }
3214
3215 let (transaction_accounts, instruction_accounts) = get_accounts(
3217 &payer_address,
3218 &buffer_address,
3219 &upgrade_authority_address,
3220 &upgrade_authority_address,
3221 &elf,
3222 );
3223 let programdata_address = instruction_accounts.get(1).unwrap().pubkey;
3224 let accounts = process_instruction(
3225 elf.len(),
3226 transaction_accounts,
3227 instruction_accounts,
3228 Ok(()),
3229 );
3230 let min_programdata_balance =
3231 Rent::default().minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len()));
3232 assert_eq!(min_programdata_balance, accounts.get(1).unwrap().lamports());
3233 assert_eq!(2, accounts.first().unwrap().lamports());
3234 assert_eq!(0, accounts.get(3).unwrap().lamports());
3235 assert_eq!(
3236 UpgradeableLoaderState::size_of_buffer(0),
3237 accounts.get(3).unwrap().data().len()
3238 );
3239 let state: UpgradeableLoaderState = accounts.get(1).unwrap().state().unwrap();
3240 assert_eq!(
3241 state,
3242 UpgradeableLoaderState::ProgramData {
3243 slot: SLOT,
3244 upgrade_authority_address: Some(upgrade_authority_address),
3245 }
3246 );
3247 for (i, byte) in accounts
3248 .get(1)
3249 .unwrap()
3250 .data()
3251 .get(
3252 UpgradeableLoaderState::size_of_programdata_metadata()
3253 ..UpgradeableLoaderState::size_of_programdata(elf.len()),
3254 )
3255 .unwrap()
3256 .iter()
3257 .enumerate()
3258 {
3259 assert_eq!(*elf.get(i).unwrap(), *byte);
3260 }
3261 let state: UpgradeableLoaderState = accounts.get(2).unwrap().state().unwrap();
3262 assert_eq!(
3263 state,
3264 UpgradeableLoaderState::Program {
3265 programdata_address,
3266 }
3267 );
3268 assert!(accounts.get(2).unwrap().executable());
3269
3270 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
3272 &payer_address,
3273 &buffer_address,
3274 &upgrade_authority_address,
3275 &upgrade_authority_address,
3276 &elf,
3277 );
3278 let invalid_upgrade_authority_address = Pubkey::new_unique();
3279 transaction_accounts.get_mut(7).unwrap().0 = invalid_upgrade_authority_address;
3280 instruction_accounts.get_mut(7).unwrap().pubkey = invalid_upgrade_authority_address;
3281 process_instruction(
3282 elf.len(),
3283 transaction_accounts,
3284 instruction_accounts,
3285 Err(InstructionError::IncorrectAuthority),
3286 );
3287
3288 let (transaction_accounts, mut instruction_accounts) = get_accounts(
3290 &payer_address,
3291 &buffer_address,
3292 &upgrade_authority_address,
3293 &upgrade_authority_address,
3294 &elf,
3295 );
3296 instruction_accounts.get_mut(7).unwrap().is_signer = false;
3297 process_instruction(
3298 elf.len(),
3299 transaction_accounts,
3300 instruction_accounts,
3301 Err(InstructionError::MissingRequiredSignature),
3302 );
3303
3304 let (transaction_accounts, mut instruction_accounts) = get_accounts(
3306 &payer_address,
3307 &buffer_address,
3308 &upgrade_authority_address,
3309 &upgrade_authority_address,
3310 &elf,
3311 );
3312 *instruction_accounts.get_mut(0).unwrap() = instruction_accounts.get(3).unwrap().clone();
3313 process_instruction(
3314 elf.len(),
3315 transaction_accounts,
3316 instruction_accounts,
3317 Err(InstructionError::AccountBorrowFailed),
3318 );
3319
3320 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3329 &payer_address,
3330 &buffer_address,
3331 &upgrade_authority_address,
3332 &upgrade_authority_address,
3333 &elf,
3334 );
3335 transaction_accounts
3336 .get_mut(2)
3337 .unwrap()
3338 .1
3339 .set_owner(Pubkey::new_unique());
3340 process_instruction(
3341 elf.len(),
3342 transaction_accounts,
3343 instruction_accounts,
3344 Err(InstructionError::ExternalAccountDataModified),
3345 );
3346
3347 let (transaction_accounts, mut instruction_accounts) = get_accounts(
3354 &payer_address,
3355 &buffer_address,
3356 &upgrade_authority_address,
3357 &upgrade_authority_address,
3358 &elf,
3359 );
3360 instruction_accounts.get_mut(2).unwrap().is_writable = false;
3361 process_instruction(
3362 elf.len(),
3363 transaction_accounts,
3364 instruction_accounts,
3365 Err(InstructionError::ReadonlyDataModified),
3366 );
3367
3368 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3370 &payer_address,
3371 &buffer_address,
3372 &upgrade_authority_address,
3373 &upgrade_authority_address,
3374 &elf,
3375 );
3376 transaction_accounts
3377 .get_mut(2)
3378 .unwrap()
3379 .1
3380 .set_state(&UpgradeableLoaderState::Program {
3381 programdata_address: Pubkey::new_unique(),
3382 })
3383 .unwrap();
3384 process_instruction(
3385 elf.len(),
3386 transaction_accounts,
3387 instruction_accounts,
3388 Err(InstructionError::AccountAlreadyInitialized),
3389 );
3390
3391 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3393 &payer_address,
3394 &buffer_address,
3395 &upgrade_authority_address,
3396 &upgrade_authority_address,
3397 &elf,
3398 );
3399 truncate_data(&mut transaction_accounts.get_mut(2).unwrap().1, 5);
3400 process_instruction(
3401 elf.len(),
3402 transaction_accounts,
3403 instruction_accounts,
3404 Err(InstructionError::AccountDataTooSmall),
3405 );
3406
3407 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3409 &payer_address,
3410 &buffer_address,
3411 &upgrade_authority_address,
3412 &upgrade_authority_address,
3413 &elf,
3414 );
3415 transaction_accounts.get_mut(2).unwrap().1.set_lamports(1);
3416 process_instruction(
3417 elf.len(),
3418 transaction_accounts,
3419 instruction_accounts,
3420 Err(InstructionError::ExecutableAccountNotRentExempt),
3421 );
3422
3423 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
3425 &payer_address,
3426 &buffer_address,
3427 &upgrade_authority_address,
3428 &upgrade_authority_address,
3429 &elf,
3430 );
3431 let invalid_programdata_address = Pubkey::new_unique();
3432 transaction_accounts.get_mut(1).unwrap().0 = invalid_programdata_address;
3433 instruction_accounts.get_mut(1).unwrap().pubkey = invalid_programdata_address;
3434 process_instruction(
3435 elf.len(),
3436 transaction_accounts,
3437 instruction_accounts,
3438 Err(InstructionError::InvalidArgument),
3439 );
3440
3441 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3443 &payer_address,
3444 &buffer_address,
3445 &upgrade_authority_address,
3446 &upgrade_authority_address,
3447 &elf,
3448 );
3449 transaction_accounts
3450 .get_mut(3)
3451 .unwrap()
3452 .1
3453 .set_state(&UpgradeableLoaderState::Uninitialized)
3454 .unwrap();
3455 process_instruction(
3456 elf.len(),
3457 transaction_accounts,
3458 instruction_accounts,
3459 Err(InstructionError::InvalidArgument),
3460 );
3461
3462 for buffer_balance in [0, 1_000_000, 15 * 1_000_000_000] {
3464 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
3465 &payer_address,
3466 &buffer_address,
3467 &upgrade_authority_address,
3468 &upgrade_authority_address,
3469 &elf,
3470 );
3471 transaction_accounts
3472 .get_mut(3)
3473 .unwrap()
3474 .1
3475 .set_lamports(buffer_balance);
3476 instruction_accounts.get_mut(3).unwrap().is_writable = false;
3477 process_instruction(
3478 elf.len(),
3479 transaction_accounts,
3480 instruction_accounts,
3481 Err(InstructionError::InvalidArgument),
3482 );
3483 }
3484
3485 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3491 &payer_address,
3492 &buffer_address,
3493 &upgrade_authority_address,
3494 &upgrade_authority_address,
3495 &elf,
3496 );
3497 {
3498 let required_rent = Rent::default()
3500 .minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len()));
3501 let programdata = &transaction_accounts.get(1).unwrap().1;
3502 assert!(programdata.lamports() < required_rent);
3503 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
3504 buffer.set_owner(Pubkey::new_unique());
3505 buffer.set_lamports(required_rent);
3506 }
3507 process_instruction(
3508 elf.len(),
3509 transaction_accounts,
3510 instruction_accounts,
3511 Err(InstructionError::IncorrectProgramId),
3512 );
3513
3514 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3519 &payer_address,
3520 &buffer_address,
3521 &upgrade_authority_address,
3522 &upgrade_authority_address,
3523 &elf,
3524 );
3525 {
3526 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
3528 buffer.set_owner(Pubkey::new_unique());
3529 buffer.set_lamports(0);
3530 }
3531 process_instruction(
3532 elf.len(),
3533 transaction_accounts,
3534 instruction_accounts,
3535 Err(InstructionError::IncorrectProgramId),
3536 );
3537
3538 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3544 &payer_address,
3545 &buffer_address,
3546 &upgrade_authority_address,
3547 &upgrade_authority_address,
3548 &elf,
3549 );
3550 {
3551 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
3553 buffer.set_owner(Pubkey::new_unique());
3554 buffer.set_lamports(0);
3555 truncate_data(buffer, UpgradeableLoaderState::size_of_buffer(0));
3556 }
3557 process_instruction(
3558 elf.len(),
3559 transaction_accounts,
3560 instruction_accounts,
3561 Err(InstructionError::IncorrectProgramId),
3562 );
3563
3564 let (transaction_accounts, instruction_accounts) = get_accounts(
3566 &payer_address,
3567 &buffer_address,
3568 &upgrade_authority_address,
3569 &upgrade_authority_address,
3570 &elf,
3571 );
3572 process_instruction(
3573 elf.len().saturating_sub(1),
3574 transaction_accounts,
3575 instruction_accounts,
3576 Err(InstructionError::AccountDataTooSmall),
3577 );
3578
3579 let (transaction_accounts, instruction_accounts) = get_accounts(
3581 &payer_address,
3582 &buffer_address,
3583 &upgrade_authority_address,
3584 &upgrade_authority_address,
3585 &elf,
3586 );
3587 process_instruction(
3588 MAX_PERMITTED_DATA_LENGTH as usize,
3589 transaction_accounts,
3590 instruction_accounts,
3591 Err(InstructionError::InvalidArgument),
3592 );
3593
3594 let (transaction_accounts, instruction_accounts) = get_accounts(
3596 &payer_address,
3597 &buffer_address,
3598 &buffer_address,
3599 &upgrade_authority_address,
3600 &elf,
3601 );
3602 process_instruction(
3603 elf.len(),
3604 transaction_accounts,
3605 instruction_accounts,
3606 Err(InstructionError::IncorrectAuthority),
3607 );
3608
3609 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3611 &payer_address,
3612 &buffer_address,
3613 &buffer_address,
3614 &upgrade_authority_address,
3615 &elf,
3616 );
3617 transaction_accounts
3618 .get_mut(3)
3619 .unwrap()
3620 .1
3621 .set_state(&UpgradeableLoaderState::Buffer {
3622 authority_address: None,
3623 })
3624 .unwrap();
3625 process_instruction(
3626 elf.len(),
3627 transaction_accounts,
3628 instruction_accounts,
3629 Err(InstructionError::IncorrectAuthority),
3630 );
3631
3632 let mut file =
3634 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
3635 let mut elf = Vec::new();
3636 file.read_to_end(&mut elf).unwrap();
3637 let (transaction_accounts, instruction_accounts) = get_accounts(
3638 &payer_address,
3639 &buffer_address,
3640 &upgrade_authority_address,
3641 &upgrade_authority_address,
3642 &elf,
3643 );
3644 process_instruction(
3645 elf.len(),
3646 transaction_accounts,
3647 instruction_accounts,
3648 Err(InstructionError::InvalidAccountData),
3649 );
3650 }
3651
3652 #[test]
3653 fn test_bpf_loader_upgradeable_set_upgrade_authority() {
3654 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::SetAuthority).unwrap();
3655 let loader_id = bpf_loader_upgradeable::id();
3656 let slot = 0;
3657 let upgrade_authority_address = Pubkey::new_unique();
3658 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3659 let new_upgrade_authority_address = Pubkey::new_unique();
3660 let new_upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3661 let program_address = Pubkey::new_unique();
3662 let (programdata_address, _) = Pubkey::find_program_address(
3663 &[program_address.as_ref()],
3664 &bpf_loader_upgradeable::id(),
3665 );
3666 let mut programdata_account = AccountSharedData::new(
3667 1,
3668 UpgradeableLoaderState::size_of_programdata(0),
3669 &bpf_loader_upgradeable::id(),
3670 );
3671 programdata_account
3672 .set_state(&UpgradeableLoaderState::ProgramData {
3673 slot,
3674 upgrade_authority_address: Some(upgrade_authority_address),
3675 })
3676 .unwrap();
3677 let programdata_meta = AccountMeta {
3678 pubkey: programdata_address,
3679 is_signer: false,
3680 is_writable: true,
3681 };
3682 let upgrade_authority_meta = AccountMeta {
3683 pubkey: upgrade_authority_address,
3684 is_signer: true,
3685 is_writable: false,
3686 };
3687 let new_upgrade_authority_meta = AccountMeta {
3688 pubkey: new_upgrade_authority_address,
3689 is_signer: false,
3690 is_writable: false,
3691 };
3692
3693 let accounts = process_instruction(
3695 &loader_id,
3696 &instruction,
3697 vec![
3698 (programdata_address, programdata_account.clone()),
3699 (upgrade_authority_address, upgrade_authority_account.clone()),
3700 (
3701 new_upgrade_authority_address,
3702 new_upgrade_authority_account.clone(),
3703 ),
3704 ],
3705 vec![
3706 programdata_meta.clone(),
3707 upgrade_authority_meta.clone(),
3708 new_upgrade_authority_meta.clone(),
3709 ],
3710 Ok(()),
3711 );
3712 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3713 assert_eq!(
3714 state,
3715 UpgradeableLoaderState::ProgramData {
3716 slot,
3717 upgrade_authority_address: Some(new_upgrade_authority_address),
3718 }
3719 );
3720
3721 let accounts = process_instruction(
3723 &loader_id,
3724 &instruction,
3725 vec![
3726 (programdata_address, programdata_account.clone()),
3727 (upgrade_authority_address, upgrade_authority_account.clone()),
3728 ],
3729 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3730 Ok(()),
3731 );
3732 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3733 assert_eq!(
3734 state,
3735 UpgradeableLoaderState::ProgramData {
3736 slot,
3737 upgrade_authority_address: None,
3738 }
3739 );
3740
3741 let mut file =
3743 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
3744 let mut elf = Vec::new();
3745 file.read_to_end(&mut elf).unwrap();
3746 programdata_account.resize(UpgradeableLoaderState::size_of_programdata(elf.len()), 0);
3747 programdata_account
3748 .data_as_mut_slice()
3749 .get_mut(UpgradeableLoaderState::size_of_programdata_metadata()..)
3750 .unwrap()
3751 .copy_from_slice(&elf);
3752 process_instruction(
3753 &loader_id,
3754 &instruction,
3755 vec![
3756 (programdata_address, programdata_account.clone()),
3757 (upgrade_authority_address, upgrade_authority_account.clone()),
3758 ],
3759 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3760 Err(InstructionError::InvalidAccountData),
3761 );
3762
3763 process_instruction(
3765 &loader_id,
3766 &instruction,
3767 vec![
3768 (programdata_address, programdata_account.clone()),
3769 (upgrade_authority_address, upgrade_authority_account.clone()),
3770 ],
3771 vec![
3772 programdata_meta.clone(),
3773 AccountMeta {
3774 pubkey: upgrade_authority_address,
3775 is_signer: false,
3776 is_writable: false,
3777 },
3778 ],
3779 Err(InstructionError::MissingRequiredSignature),
3780 );
3781
3782 let invalid_upgrade_authority_address = Pubkey::new_unique();
3784 process_instruction(
3785 &loader_id,
3786 &instruction,
3787 vec![
3788 (programdata_address, programdata_account.clone()),
3789 (
3790 invalid_upgrade_authority_address,
3791 upgrade_authority_account.clone(),
3792 ),
3793 (new_upgrade_authority_address, new_upgrade_authority_account),
3794 ],
3795 vec![
3796 programdata_meta.clone(),
3797 AccountMeta {
3798 pubkey: invalid_upgrade_authority_address,
3799 is_signer: true,
3800 is_writable: false,
3801 },
3802 new_upgrade_authority_meta,
3803 ],
3804 Err(InstructionError::IncorrectAuthority),
3805 );
3806
3807 programdata_account
3809 .set_state(&UpgradeableLoaderState::ProgramData {
3810 slot,
3811 upgrade_authority_address: None,
3812 })
3813 .unwrap();
3814 process_instruction(
3815 &loader_id,
3816 &instruction,
3817 vec![
3818 (programdata_address, programdata_account.clone()),
3819 (upgrade_authority_address, upgrade_authority_account.clone()),
3820 ],
3821 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3822 Err(InstructionError::Immutable),
3823 );
3824
3825 programdata_account
3827 .set_state(&UpgradeableLoaderState::Program {
3828 programdata_address: Pubkey::new_unique(),
3829 })
3830 .unwrap();
3831 process_instruction(
3832 &loader_id,
3833 &instruction,
3834 vec![
3835 (programdata_address, programdata_account.clone()),
3836 (upgrade_authority_address, upgrade_authority_account),
3837 ],
3838 vec![programdata_meta, upgrade_authority_meta],
3839 Err(InstructionError::InvalidArgument),
3840 );
3841 }
3842
3843 #[test]
3844 fn test_bpf_loader_upgradeable_set_upgrade_authority_checked() {
3845 let instruction =
3846 bincode::serialize(&UpgradeableLoaderInstruction::SetAuthorityChecked).unwrap();
3847 let loader_id = bpf_loader_upgradeable::id();
3848 let slot = 0;
3849 let upgrade_authority_address = Pubkey::new_unique();
3850 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3851 let new_upgrade_authority_address = Pubkey::new_unique();
3852 let new_upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3853 let program_address = Pubkey::new_unique();
3854 let (programdata_address, _) = Pubkey::find_program_address(
3855 &[program_address.as_ref()],
3856 &bpf_loader_upgradeable::id(),
3857 );
3858 let mut programdata_account = AccountSharedData::new(
3859 1,
3860 UpgradeableLoaderState::size_of_programdata(0),
3861 &bpf_loader_upgradeable::id(),
3862 );
3863 programdata_account
3864 .set_state(&UpgradeableLoaderState::ProgramData {
3865 slot,
3866 upgrade_authority_address: Some(upgrade_authority_address),
3867 })
3868 .unwrap();
3869 let programdata_meta = AccountMeta {
3870 pubkey: programdata_address,
3871 is_signer: false,
3872 is_writable: true,
3873 };
3874 let upgrade_authority_meta = AccountMeta {
3875 pubkey: upgrade_authority_address,
3876 is_signer: true,
3877 is_writable: false,
3878 };
3879 let new_upgrade_authority_meta = AccountMeta {
3880 pubkey: new_upgrade_authority_address,
3881 is_signer: true,
3882 is_writable: false,
3883 };
3884
3885 let accounts = process_instruction(
3887 &loader_id,
3888 &instruction,
3889 vec![
3890 (programdata_address, programdata_account.clone()),
3891 (upgrade_authority_address, upgrade_authority_account.clone()),
3892 (
3893 new_upgrade_authority_address,
3894 new_upgrade_authority_account.clone(),
3895 ),
3896 ],
3897 vec![
3898 programdata_meta.clone(),
3899 upgrade_authority_meta.clone(),
3900 new_upgrade_authority_meta.clone(),
3901 ],
3902 Ok(()),
3903 );
3904
3905 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3906 assert_eq!(
3907 state,
3908 UpgradeableLoaderState::ProgramData {
3909 slot,
3910 upgrade_authority_address: Some(new_upgrade_authority_address),
3911 }
3912 );
3913
3914 process_instruction(
3916 &loader_id,
3917 &instruction,
3918 vec![
3919 (programdata_address, programdata_account.clone()),
3920 (upgrade_authority_address, upgrade_authority_account.clone()),
3921 ],
3922 vec![
3923 programdata_meta.clone(),
3924 upgrade_authority_meta.clone(),
3925 upgrade_authority_meta.clone(),
3926 ],
3927 Ok(()),
3928 );
3929
3930 process_instruction(
3932 &loader_id,
3933 &instruction,
3934 vec![
3935 (programdata_address, programdata_account.clone()),
3936 (upgrade_authority_address, upgrade_authority_account.clone()),
3937 (
3938 new_upgrade_authority_address,
3939 new_upgrade_authority_account.clone(),
3940 ),
3941 ],
3942 vec![programdata_meta.clone(), new_upgrade_authority_meta.clone()],
3943 Err(InstructionError::MissingAccount),
3944 );
3945
3946 process_instruction(
3948 &loader_id,
3949 &instruction,
3950 vec![
3951 (programdata_address, programdata_account.clone()),
3952 (upgrade_authority_address, upgrade_authority_account.clone()),
3953 (
3954 new_upgrade_authority_address,
3955 new_upgrade_authority_account.clone(),
3956 ),
3957 ],
3958 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3959 Err(InstructionError::MissingAccount),
3960 );
3961
3962 process_instruction(
3964 &loader_id,
3965 &instruction,
3966 vec![
3967 (programdata_address, programdata_account.clone()),
3968 (upgrade_authority_address, upgrade_authority_account.clone()),
3969 (
3970 new_upgrade_authority_address,
3971 new_upgrade_authority_account.clone(),
3972 ),
3973 ],
3974 vec![
3975 programdata_meta.clone(),
3976 AccountMeta {
3977 pubkey: upgrade_authority_address,
3978 is_signer: false,
3979 is_writable: false,
3980 },
3981 new_upgrade_authority_meta.clone(),
3982 ],
3983 Err(InstructionError::MissingRequiredSignature),
3984 );
3985
3986 process_instruction(
3988 &loader_id,
3989 &instruction,
3990 vec![
3991 (programdata_address, programdata_account.clone()),
3992 (upgrade_authority_address, upgrade_authority_account.clone()),
3993 (
3994 new_upgrade_authority_address,
3995 new_upgrade_authority_account.clone(),
3996 ),
3997 ],
3998 vec![
3999 programdata_meta.clone(),
4000 upgrade_authority_meta.clone(),
4001 AccountMeta {
4002 pubkey: new_upgrade_authority_address,
4003 is_signer: false,
4004 is_writable: false,
4005 },
4006 ],
4007 Err(InstructionError::MissingRequiredSignature),
4008 );
4009
4010 let invalid_upgrade_authority_address = Pubkey::new_unique();
4012 process_instruction(
4013 &loader_id,
4014 &instruction,
4015 vec![
4016 (programdata_address, programdata_account.clone()),
4017 (
4018 invalid_upgrade_authority_address,
4019 upgrade_authority_account.clone(),
4020 ),
4021 (new_upgrade_authority_address, new_upgrade_authority_account),
4022 ],
4023 vec![
4024 programdata_meta.clone(),
4025 AccountMeta {
4026 pubkey: invalid_upgrade_authority_address,
4027 is_signer: true,
4028 is_writable: false,
4029 },
4030 new_upgrade_authority_meta.clone(),
4031 ],
4032 Err(InstructionError::IncorrectAuthority),
4033 );
4034
4035 programdata_account
4037 .set_state(&UpgradeableLoaderState::ProgramData {
4038 slot,
4039 upgrade_authority_address: None,
4040 })
4041 .unwrap();
4042 process_instruction(
4043 &loader_id,
4044 &instruction,
4045 vec![
4046 (programdata_address, programdata_account.clone()),
4047 (upgrade_authority_address, upgrade_authority_account.clone()),
4048 ],
4049 vec![
4050 programdata_meta.clone(),
4051 upgrade_authority_meta.clone(),
4052 new_upgrade_authority_meta.clone(),
4053 ],
4054 Err(InstructionError::Immutable),
4055 );
4056
4057 programdata_account
4059 .set_state(&UpgradeableLoaderState::Program {
4060 programdata_address: Pubkey::new_unique(),
4061 })
4062 .unwrap();
4063 process_instruction(
4064 &loader_id,
4065 &instruction,
4066 vec![
4067 (programdata_address, programdata_account.clone()),
4068 (upgrade_authority_address, upgrade_authority_account),
4069 ],
4070 vec![
4071 programdata_meta,
4072 upgrade_authority_meta,
4073 new_upgrade_authority_meta,
4074 ],
4075 Err(InstructionError::InvalidArgument),
4076 );
4077 }
4078
4079 #[test]
4080 fn test_bpf_loader_upgradeable_set_buffer_authority() {
4081 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::SetAuthority).unwrap();
4082 let loader_id = bpf_loader_upgradeable::id();
4083 let invalid_authority_address = Pubkey::new_unique();
4084 let authority_address = Pubkey::new_unique();
4085 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4086 let new_authority_address = Pubkey::new_unique();
4087 let new_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4088 let buffer_address = Pubkey::new_unique();
4089 let mut buffer_account =
4090 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(0), &loader_id);
4091 buffer_account
4092 .set_state(&UpgradeableLoaderState::Buffer {
4093 authority_address: Some(authority_address),
4094 })
4095 .unwrap();
4096 let mut transaction_accounts = vec![
4097 (buffer_address, buffer_account.clone()),
4098 (authority_address, authority_account.clone()),
4099 (new_authority_address, new_authority_account.clone()),
4100 ];
4101 let buffer_meta = AccountMeta {
4102 pubkey: buffer_address,
4103 is_signer: false,
4104 is_writable: true,
4105 };
4106 let authority_meta = AccountMeta {
4107 pubkey: authority_address,
4108 is_signer: true,
4109 is_writable: false,
4110 };
4111 let new_authority_meta = AccountMeta {
4112 pubkey: new_authority_address,
4113 is_signer: false,
4114 is_writable: false,
4115 };
4116
4117 let accounts = process_instruction(
4119 &loader_id,
4120 &instruction,
4121 transaction_accounts.clone(),
4122 vec![buffer_meta.clone(), authority_meta.clone()],
4123 Err(InstructionError::IncorrectAuthority),
4124 );
4125 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4126 assert_eq!(
4127 state,
4128 UpgradeableLoaderState::Buffer {
4129 authority_address: Some(authority_address),
4130 }
4131 );
4132
4133 buffer_account
4135 .set_state(&UpgradeableLoaderState::Buffer {
4136 authority_address: Some(authority_address),
4137 })
4138 .unwrap();
4139 let accounts = process_instruction(
4140 &loader_id,
4141 &instruction,
4142 transaction_accounts.clone(),
4143 vec![
4144 buffer_meta.clone(),
4145 authority_meta.clone(),
4146 new_authority_meta.clone(),
4147 ],
4148 Ok(()),
4149 );
4150 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4151 assert_eq!(
4152 state,
4153 UpgradeableLoaderState::Buffer {
4154 authority_address: Some(new_authority_address),
4155 }
4156 );
4157
4158 process_instruction(
4160 &loader_id,
4161 &instruction,
4162 transaction_accounts.clone(),
4163 vec![
4164 buffer_meta.clone(),
4165 AccountMeta {
4166 pubkey: authority_address,
4167 is_signer: false,
4168 is_writable: false,
4169 },
4170 new_authority_meta.clone(),
4171 ],
4172 Err(InstructionError::MissingRequiredSignature),
4173 );
4174
4175 process_instruction(
4177 &loader_id,
4178 &instruction,
4179 vec![
4180 (buffer_address, buffer_account.clone()),
4181 (invalid_authority_address, authority_account),
4182 (new_authority_address, new_authority_account),
4183 ],
4184 vec![
4185 buffer_meta.clone(),
4186 AccountMeta {
4187 pubkey: invalid_authority_address,
4188 is_signer: true,
4189 is_writable: false,
4190 },
4191 new_authority_meta.clone(),
4192 ],
4193 Err(InstructionError::IncorrectAuthority),
4194 );
4195
4196 process_instruction(
4198 &loader_id,
4199 &instruction,
4200 transaction_accounts.clone(),
4201 vec![buffer_meta.clone(), authority_meta.clone()],
4202 Err(InstructionError::IncorrectAuthority),
4203 );
4204
4205 transaction_accounts
4207 .get_mut(0)
4208 .unwrap()
4209 .1
4210 .set_state(&UpgradeableLoaderState::Buffer {
4211 authority_address: None,
4212 })
4213 .unwrap();
4214 process_instruction(
4215 &loader_id,
4216 &instruction,
4217 transaction_accounts.clone(),
4218 vec![
4219 buffer_meta.clone(),
4220 authority_meta.clone(),
4221 new_authority_meta.clone(),
4222 ],
4223 Err(InstructionError::Immutable),
4224 );
4225
4226 transaction_accounts
4228 .get_mut(0)
4229 .unwrap()
4230 .1
4231 .set_state(&UpgradeableLoaderState::Program {
4232 programdata_address: Pubkey::new_unique(),
4233 })
4234 .unwrap();
4235 process_instruction(
4236 &loader_id,
4237 &instruction,
4238 transaction_accounts.clone(),
4239 vec![buffer_meta, authority_meta, new_authority_meta],
4240 Err(InstructionError::InvalidArgument),
4241 );
4242 }
4243
4244 #[test]
4245 fn test_bpf_loader_upgradeable_set_buffer_authority_checked() {
4246 let instruction =
4247 bincode::serialize(&UpgradeableLoaderInstruction::SetAuthorityChecked).unwrap();
4248 let loader_id = bpf_loader_upgradeable::id();
4249 let invalid_authority_address = Pubkey::new_unique();
4250 let authority_address = Pubkey::new_unique();
4251 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4252 let new_authority_address = Pubkey::new_unique();
4253 let new_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4254 let buffer_address = Pubkey::new_unique();
4255 let mut buffer_account =
4256 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(0), &loader_id);
4257 buffer_account
4258 .set_state(&UpgradeableLoaderState::Buffer {
4259 authority_address: Some(authority_address),
4260 })
4261 .unwrap();
4262 let mut transaction_accounts = vec![
4263 (buffer_address, buffer_account.clone()),
4264 (authority_address, authority_account.clone()),
4265 (new_authority_address, new_authority_account.clone()),
4266 ];
4267 let buffer_meta = AccountMeta {
4268 pubkey: buffer_address,
4269 is_signer: false,
4270 is_writable: true,
4271 };
4272 let authority_meta = AccountMeta {
4273 pubkey: authority_address,
4274 is_signer: true,
4275 is_writable: false,
4276 };
4277 let new_authority_meta = AccountMeta {
4278 pubkey: new_authority_address,
4279 is_signer: true,
4280 is_writable: false,
4281 };
4282
4283 buffer_account
4285 .set_state(&UpgradeableLoaderState::Buffer {
4286 authority_address: Some(authority_address),
4287 })
4288 .unwrap();
4289 let accounts = process_instruction(
4290 &loader_id,
4291 &instruction,
4292 transaction_accounts.clone(),
4293 vec![
4294 buffer_meta.clone(),
4295 authority_meta.clone(),
4296 new_authority_meta.clone(),
4297 ],
4298 Ok(()),
4299 );
4300 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4301 assert_eq!(
4302 state,
4303 UpgradeableLoaderState::Buffer {
4304 authority_address: Some(new_authority_address),
4305 }
4306 );
4307
4308 process_instruction(
4310 &loader_id,
4311 &instruction,
4312 transaction_accounts.clone(),
4313 vec![
4314 buffer_meta.clone(),
4315 authority_meta.clone(),
4316 authority_meta.clone(),
4317 ],
4318 Ok(()),
4319 );
4320
4321 process_instruction(
4323 &loader_id,
4324 &instruction,
4325 transaction_accounts.clone(),
4326 vec![buffer_meta.clone(), new_authority_meta.clone()],
4327 Err(InstructionError::MissingAccount),
4328 );
4329
4330 process_instruction(
4332 &loader_id,
4333 &instruction,
4334 transaction_accounts.clone(),
4335 vec![buffer_meta.clone(), authority_meta.clone()],
4336 Err(InstructionError::MissingAccount),
4337 );
4338
4339 process_instruction(
4341 &loader_id,
4342 &instruction,
4343 vec![
4344 (buffer_address, buffer_account.clone()),
4345 (invalid_authority_address, authority_account),
4346 (new_authority_address, new_authority_account),
4347 ],
4348 vec![
4349 buffer_meta.clone(),
4350 AccountMeta {
4351 pubkey: invalid_authority_address,
4352 is_signer: true,
4353 is_writable: false,
4354 },
4355 new_authority_meta.clone(),
4356 ],
4357 Err(InstructionError::IncorrectAuthority),
4358 );
4359
4360 process_instruction(
4362 &loader_id,
4363 &instruction,
4364 transaction_accounts.clone(),
4365 vec![
4366 buffer_meta.clone(),
4367 AccountMeta {
4368 pubkey: authority_address,
4369 is_signer: false,
4370 is_writable: false,
4371 },
4372 new_authority_meta.clone(),
4373 ],
4374 Err(InstructionError::MissingRequiredSignature),
4375 );
4376
4377 process_instruction(
4379 &loader_id,
4380 &instruction,
4381 transaction_accounts.clone(),
4382 vec![
4383 buffer_meta.clone(),
4384 authority_meta.clone(),
4385 AccountMeta {
4386 pubkey: new_authority_address,
4387 is_signer: false,
4388 is_writable: false,
4389 },
4390 ],
4391 Err(InstructionError::MissingRequiredSignature),
4392 );
4393
4394 transaction_accounts
4396 .get_mut(0)
4397 .unwrap()
4398 .1
4399 .set_state(&UpgradeableLoaderState::Program {
4400 programdata_address: Pubkey::new_unique(),
4401 })
4402 .unwrap();
4403 process_instruction(
4404 &loader_id,
4405 &instruction,
4406 transaction_accounts.clone(),
4407 vec![
4408 buffer_meta.clone(),
4409 authority_meta.clone(),
4410 new_authority_meta.clone(),
4411 ],
4412 Err(InstructionError::InvalidArgument),
4413 );
4414
4415 transaction_accounts
4417 .get_mut(0)
4418 .unwrap()
4419 .1
4420 .set_state(&UpgradeableLoaderState::Buffer {
4421 authority_address: None,
4422 })
4423 .unwrap();
4424 process_instruction(
4425 &loader_id,
4426 &instruction,
4427 transaction_accounts.clone(),
4428 vec![buffer_meta, authority_meta, new_authority_meta],
4429 Err(InstructionError::Immutable),
4430 );
4431 }
4432
4433 #[test]
4434 fn test_bpf_loader_upgradeable_close() {
4435 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Close).unwrap();
4436 let loader_id = bpf_loader_upgradeable::id();
4437 let invalid_authority_address = Pubkey::new_unique();
4438 let authority_address = Pubkey::new_unique();
4439 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4440 let recipient_address = Pubkey::new_unique();
4441 let recipient_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4442 let buffer_address = Pubkey::new_unique();
4443 let mut buffer_account =
4444 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(128), &loader_id);
4445 buffer_account
4446 .set_state(&UpgradeableLoaderState::Buffer {
4447 authority_address: Some(authority_address),
4448 })
4449 .unwrap();
4450 let uninitialized_address = Pubkey::new_unique();
4451 let mut uninitialized_account = AccountSharedData::new(
4452 1,
4453 UpgradeableLoaderState::size_of_programdata(0),
4454 &loader_id,
4455 );
4456 uninitialized_account
4457 .set_state(&UpgradeableLoaderState::Uninitialized)
4458 .unwrap();
4459 let programdata_address = Pubkey::new_unique();
4460 let mut programdata_account = AccountSharedData::new(
4461 1,
4462 UpgradeableLoaderState::size_of_programdata(128),
4463 &loader_id,
4464 );
4465 programdata_account
4466 .set_state(&UpgradeableLoaderState::ProgramData {
4467 slot: 0,
4468 upgrade_authority_address: Some(authority_address),
4469 })
4470 .unwrap();
4471 let program_address = Pubkey::new_unique();
4472 let mut program_account =
4473 AccountSharedData::new(1, UpgradeableLoaderState::size_of_program(), &loader_id);
4474 program_account.set_executable(true);
4475 program_account
4476 .set_state(&UpgradeableLoaderState::Program {
4477 programdata_address,
4478 })
4479 .unwrap();
4480 let clock_account = create_sysvar_account(&Clock {
4481 slot: 1,
4482 ..Clock::default()
4483 });
4484 let transaction_accounts = vec![
4485 (buffer_address, buffer_account.clone()),
4486 (recipient_address, recipient_account.clone()),
4487 (authority_address, authority_account.clone()),
4488 ];
4489 let buffer_meta = AccountMeta {
4490 pubkey: buffer_address,
4491 is_signer: false,
4492 is_writable: true,
4493 };
4494 let recipient_meta = AccountMeta {
4495 pubkey: recipient_address,
4496 is_signer: false,
4497 is_writable: true,
4498 };
4499 let authority_meta = AccountMeta {
4500 pubkey: authority_address,
4501 is_signer: true,
4502 is_writable: false,
4503 };
4504
4505 let accounts = process_instruction(
4507 &loader_id,
4508 &instruction,
4509 transaction_accounts,
4510 vec![
4511 buffer_meta.clone(),
4512 recipient_meta.clone(),
4513 authority_meta.clone(),
4514 ],
4515 Ok(()),
4516 );
4517 assert_eq!(0, accounts.first().unwrap().lamports());
4518 assert_eq!(2, accounts.get(1).unwrap().lamports());
4519 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4520 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
4521 assert_eq!(
4522 UpgradeableLoaderState::size_of_uninitialized(),
4523 accounts.first().unwrap().data().len()
4524 );
4525
4526 process_instruction(
4528 &loader_id,
4529 &instruction,
4530 vec![
4531 (buffer_address, buffer_account.clone()),
4532 (recipient_address, recipient_account.clone()),
4533 (invalid_authority_address, authority_account.clone()),
4534 ],
4535 vec![
4536 buffer_meta,
4537 recipient_meta.clone(),
4538 AccountMeta {
4539 pubkey: invalid_authority_address,
4540 is_signer: true,
4541 is_writable: false,
4542 },
4543 ],
4544 Err(InstructionError::IncorrectAuthority),
4545 );
4546
4547 let accounts = process_instruction(
4549 &loader_id,
4550 &instruction,
4551 vec![
4552 (uninitialized_address, uninitialized_account.clone()),
4553 (recipient_address, recipient_account.clone()),
4554 (invalid_authority_address, authority_account.clone()),
4555 ],
4556 vec![
4557 AccountMeta {
4558 pubkey: uninitialized_address,
4559 is_signer: false,
4560 is_writable: true,
4561 },
4562 recipient_meta.clone(),
4563 authority_meta.clone(),
4564 ],
4565 Ok(()),
4566 );
4567 assert_eq!(0, accounts.first().unwrap().lamports());
4568 assert_eq!(2, accounts.get(1).unwrap().lamports());
4569 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4570 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
4571 assert_eq!(
4572 UpgradeableLoaderState::size_of_uninitialized(),
4573 accounts.first().unwrap().data().len()
4574 );
4575
4576 process_instruction(
4578 &loader_id,
4579 &instruction,
4580 vec![
4581 (programdata_address, programdata_account.clone()),
4582 (recipient_address, recipient_account.clone()),
4583 (authority_address, authority_account.clone()),
4584 (program_address, program_account.clone()),
4585 (sysvar::clock::id(), clock_account.clone()),
4586 ],
4587 vec![
4588 AccountMeta {
4589 pubkey: programdata_address,
4590 is_signer: false,
4591 is_writable: true,
4592 },
4593 recipient_meta.clone(),
4594 authority_meta.clone(),
4595 AccountMeta {
4596 pubkey: program_address,
4597 is_signer: false,
4598 is_writable: false,
4599 },
4600 ],
4601 Err(InstructionError::InvalidArgument),
4602 );
4603
4604 let accounts = process_instruction(
4606 &loader_id,
4607 &instruction,
4608 vec![
4609 (programdata_address, programdata_account.clone()),
4610 (recipient_address, recipient_account.clone()),
4611 (authority_address, authority_account.clone()),
4612 (program_address, program_account.clone()),
4613 (sysvar::clock::id(), clock_account.clone()),
4614 ],
4615 vec![
4616 AccountMeta {
4617 pubkey: programdata_address,
4618 is_signer: false,
4619 is_writable: true,
4620 },
4621 recipient_meta,
4622 authority_meta,
4623 AccountMeta {
4624 pubkey: program_address,
4625 is_signer: false,
4626 is_writable: true,
4627 },
4628 ],
4629 Ok(()),
4630 );
4631 assert_eq!(0, accounts.first().unwrap().lamports());
4632 assert_eq!(2, accounts.get(1).unwrap().lamports());
4633 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4634 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
4635 assert_eq!(
4636 UpgradeableLoaderState::size_of_uninitialized(),
4637 accounts.first().unwrap().data().len()
4638 );
4639
4640 programdata_account = accounts.first().unwrap().clone();
4642 program_account = accounts.get(3).unwrap().clone();
4643 process_instruction(
4644 &program_address,
4645 &[],
4646 vec![
4647 (programdata_address, programdata_account.clone()),
4648 (program_address, program_account.clone()),
4649 ],
4650 Vec::new(),
4651 Err(InstructionError::UnsupportedProgramId),
4652 );
4653
4654 process_instruction(
4656 &loader_id,
4657 &bincode::serialize(&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
4658 max_data_len: 0,
4659 })
4660 .unwrap(),
4661 vec![
4662 (recipient_address, recipient_account),
4663 (programdata_address, programdata_account),
4664 (program_address, program_account),
4665 (buffer_address, buffer_account),
4666 (sysvar::rent::id(), create_sysvar_account(&Rent::default())),
4667 (sysvar::clock::id(), clock_account),
4668 (
4669 system_program::id(),
4670 AccountSharedData::new(0, 0, &system_program::id()),
4671 ),
4672 (authority_address, authority_account),
4673 ],
4674 vec![
4675 AccountMeta {
4676 pubkey: recipient_address,
4677 is_signer: true,
4678 is_writable: true,
4679 },
4680 AccountMeta {
4681 pubkey: programdata_address,
4682 is_signer: false,
4683 is_writable: true,
4684 },
4685 AccountMeta {
4686 pubkey: program_address,
4687 is_signer: false,
4688 is_writable: true,
4689 },
4690 AccountMeta {
4691 pubkey: buffer_address,
4692 is_signer: false,
4693 is_writable: false,
4694 },
4695 AccountMeta {
4696 pubkey: sysvar::rent::id(),
4697 is_signer: false,
4698 is_writable: false,
4699 },
4700 AccountMeta {
4701 pubkey: sysvar::clock::id(),
4702 is_signer: false,
4703 is_writable: false,
4704 },
4705 AccountMeta {
4706 pubkey: system_program::id(),
4707 is_signer: false,
4708 is_writable: false,
4709 },
4710 AccountMeta {
4711 pubkey: authority_address,
4712 is_signer: false,
4713 is_writable: false,
4714 },
4715 ],
4716 Err(InstructionError::AccountAlreadyInitialized),
4717 );
4718 }
4719
4720 fn fuzz<F>(
4722 bytes: &[u8],
4723 outer_iters: usize,
4724 inner_iters: usize,
4725 offset: Range<usize>,
4726 value: Range<u8>,
4727 work: F,
4728 ) where
4729 F: Fn(&mut [u8]),
4730 {
4731 let mut rng = rand::rng();
4732 for _ in 0..outer_iters {
4733 let mut mangled_bytes = bytes.to_vec();
4734 for _ in 0..inner_iters {
4735 let offset = rng.random_range(offset.start..offset.end);
4736 let value = rng.random_range(value.start..value.end);
4737 *mangled_bytes.get_mut(offset).unwrap() = value;
4738 work(&mut mangled_bytes);
4739 }
4740 }
4741 }
4742
4743 #[test]
4744 #[ignore]
4745 fn test_fuzz() {
4746 let loader_id = bpf_loader::id();
4747 let program_id = Pubkey::new_unique();
4748
4749 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
4751 let mut elf = Vec::new();
4752 file.read_to_end(&mut elf).unwrap();
4753
4754 fuzz(
4756 &elf,
4757 1_000_000_000,
4758 100,
4759 0..elf.len(),
4760 0..255,
4761 |bytes: &mut [u8]| {
4762 let mut program_account = AccountSharedData::new(1, 0, &loader_id);
4763 program_account.set_data_from_slice(bytes);
4764 program_account.set_executable(true);
4765 process_instruction(
4766 &program_id,
4767 &[],
4768 vec![(program_id, program_account)],
4769 Vec::new(),
4770 Ok(()),
4771 );
4772 },
4773 );
4774 }
4775
4776 #[test]
4777 fn test_calculate_heap_cost() {
4778 let heap_cost = 8_u64;
4779
4780 assert_eq!(0, calculate_heap_cost(31 * 1024, heap_cost));
4784
4785 assert_eq!(0, calculate_heap_cost(32 * 1024, heap_cost));
4787
4788 assert_eq!(heap_cost, calculate_heap_cost(33 * 1024, heap_cost));
4790
4791 assert_eq!(heap_cost, calculate_heap_cost(64 * 1024, heap_cost));
4793 }
4794
4795 fn deploy_test_program(
4796 invoke_context: &mut InvokeContext,
4797 program_id: Pubkey,
4798 ) -> Result<(), InstructionError> {
4799 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
4800 let mut elf = Vec::new();
4801 file.read_to_end(&mut elf).unwrap();
4802 deploy_program!(
4803 invoke_context,
4804 &program_id,
4805 &bpf_loader_upgradeable::id(),
4806 &elf,
4807 2_u64,
4808 true, );
4810 Ok(())
4811 }
4812
4813 #[cfg(feature = "shuttle-test")]
4832 const PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS: usize = 100;
4833
4834 #[test]
4835 fn test_program_usage_count_on_upgrade() {
4836 #[cfg(feature = "shuttle-test")]
4837 shuttle::check_random(
4838 do_test_program_usage_count_on_upgrade,
4839 PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS,
4840 );
4841 #[cfg(not(feature = "shuttle-test"))]
4842 do_test_program_usage_count_on_upgrade();
4843 }
4844
4845 fn do_test_program_usage_count_on_upgrade() {
4846 let transaction_accounts = vec![(
4847 sysvar::epoch_schedule::id(),
4848 create_sysvar_account(&EpochSchedule::default()),
4849 )];
4850 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4851 let program_id = Pubkey::new_unique();
4852 let env = ProgramRuntimeEnvironment::from(BuiltinProgram::new_mock());
4853 let stats = ProgramStatistics {
4854 uses: 100.into(),
4855 ..Default::default()
4856 };
4857 let program = ProgramCacheEntry {
4858 program: ProgramCacheEntryType::Unloaded(env),
4859 account_owner: ProgramCacheEntryOwner::LoaderV2,
4860 deployment_slot: 0,
4861 stats: stats.into(),
4862 latest_access_slot: AtomicU64::new(0),
4863 };
4864 invoke_context
4865 .program_cache_for_tx_batch
4866 .replenish(program_id, Arc::new(program));
4867 invoke_context
4868 .program_cache_for_tx_batch
4869 .set_slot_for_tests(2);
4870
4871 assert_matches!(
4872 deploy_test_program(&mut invoke_context, program_id,),
4873 Ok(())
4874 );
4875
4876 let updated_program = invoke_context
4877 .program_cache_for_tx_batch
4878 .find(&program_id)
4879 .expect("Didn't find upgraded program in the cache");
4880
4881 assert_eq!(updated_program.deployment_slot, 2);
4882 assert_eq!(updated_program.stats.uses.load(Ordering::Relaxed), 100);
4883 }
4884
4885 #[test]
4886 fn test_program_usage_count_on_non_upgrade() {
4887 #[cfg(feature = "shuttle-test")]
4888 shuttle::check_random(
4889 do_test_program_usage_count_on_non_upgrade,
4890 PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS,
4891 );
4892 #[cfg(not(feature = "shuttle-test"))]
4893 do_test_program_usage_count_on_non_upgrade();
4894 }
4895
4896 fn do_test_program_usage_count_on_non_upgrade() {
4897 let transaction_accounts = vec![(
4898 sysvar::epoch_schedule::id(),
4899 create_sysvar_account(&EpochSchedule::default()),
4900 )];
4901 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4902 let program_id = Pubkey::new_unique();
4903 let env = ProgramRuntimeEnvironment::from(BuiltinProgram::new_mock());
4904 let stats = ProgramStatistics {
4905 uses: 100.into(),
4906 ..Default::default()
4907 };
4908 let program = ProgramCacheEntry {
4909 program: ProgramCacheEntryType::Unloaded(env),
4910 account_owner: ProgramCacheEntryOwner::LoaderV2,
4911 deployment_slot: 0,
4912 stats: stats.into(),
4913 latest_access_slot: AtomicU64::new(0),
4914 };
4915 invoke_context
4916 .program_cache_for_tx_batch
4917 .replenish(program_id, Arc::new(program));
4918 invoke_context
4919 .program_cache_for_tx_batch
4920 .set_slot_for_tests(2);
4921
4922 let program_id2 = Pubkey::new_unique();
4923 assert_matches!(
4924 deploy_test_program(&mut invoke_context, program_id2),
4925 Ok(())
4926 );
4927
4928 let program2 = invoke_context
4929 .program_cache_for_tx_batch
4930 .find(&program_id2)
4931 .expect("Didn't find upgraded program in the cache");
4932
4933 assert_eq!(program2.deployment_slot, 2);
4934 assert_eq!(program2.stats.uses.load(Ordering::Relaxed), 0);
4935 }
4936}