(args: LoadArgs, vm: &VirtualMachine)
| 517 | |
| 518 | #[pyfunction] |
| 519 | fn load(args: LoadArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> { |
| 520 | // Read from file object into a buffer, one object at a time. |
| 521 | // We read all available data, deserialize one object, then seek |
| 522 | // back to just after the consumed bytes. |
| 523 | let tell_before = vm |
| 524 | .call_method(&args.f, "tell", ())? |
| 525 | .try_into_value::<i64>(vm)?; |
| 526 | let read_res = vm.call_method(&args.f, "read", ())?; |
| 527 | let bytes = ArgBytesLike::try_from_object(vm, read_res)?; |
| 528 | let buf = bytes.borrow_buf(); |
| 529 | |
| 530 | let mut rdr: &[u8] = &buf; |
| 531 | let len_before = rdr.len(); |
| 532 | let result = |
| 533 | marshal::deserialize_value(&mut rdr, PyMarshalBag(vm)).map_err(|e| match e { |
| 534 | marshal::MarshalError::Eof => vm.new_exception_msg( |
| 535 | vm.ctx.exceptions.eof_error.to_owned(), |
| 536 | "marshal data too short".into(), |
| 537 | ), |
| 538 | _ => vm.new_value_error("bad marshal data"), |
| 539 | })?; |
| 540 | let consumed = len_before - rdr.len(); |
| 541 | |
| 542 | // Seek file to just after the consumed bytes |
| 543 | let new_pos = tell_before + consumed as i64; |
| 544 | vm.call_method(&args.f, "seek", (new_pos,))?; |
| 545 | |
| 546 | if !args.allow_code { |
| 547 | check_no_code(&result, vm)?; |
| 548 | } |
| 549 | Ok(result) |
| 550 | } |
| 551 | |
| 552 | /// Reject subclasses of marshallable types (int, float, complex, tuple, etc.). |
| 553 | /// Recursively check that no code objects are present. |
no test coverage detected