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