| 688 | } |
| 689 | |
| 690 | void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, bool _keepReference) const |
| 691 | { |
| 692 | /// Stack: reference [length] index |
| 693 | DataLocation location = _arrayType.location(); |
| 694 | |
| 695 | if (_doBoundsCheck) |
| 696 | { |
| 697 | // retrieve length |
| 698 | ArrayUtils::retrieveLength(_arrayType, 1); |
| 699 | // Stack: ref [length] index length |
| 700 | // check out-of-bounds access |
| 701 | m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO; |
| 702 | // out-of-bounds access throws exception |
| 703 | m_context.appendConditionalPanic(util::PanicCode::ArrayOutOfBounds); |
| 704 | } |
| 705 | if (location == DataLocation::CallData && _arrayType.isDynamicallySized()) |
| 706 | // remove length if present |
| 707 | m_context << Instruction::SWAP1 << Instruction::POP; |
| 708 | |
| 709 | // stack: <base_ref> <index> |
| 710 | switch (location) |
| 711 | { |
| 712 | case DataLocation::Memory: |
| 713 | // stack: <base_ref> <index> |
| 714 | if (!_arrayType.isByteArrayOrString()) |
| 715 | m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL; |
| 716 | if (_arrayType.isDynamicallySized()) |
| 717 | m_context << u256(32) << Instruction::ADD; |
| 718 | if (_keepReference) |
| 719 | m_context << Instruction::DUP2; |
| 720 | m_context << Instruction::ADD; |
| 721 | break; |
| 722 | case DataLocation::CallData: |
| 723 | if (!_arrayType.isByteArrayOrString()) |
| 724 | { |
| 725 | m_context << _arrayType.calldataStride(); |
| 726 | m_context << Instruction::MUL; |
| 727 | } |
| 728 | // stack: <base_ref> <index * size> |
| 729 | if (_keepReference) |
| 730 | m_context << Instruction::DUP2; |
| 731 | m_context << Instruction::ADD; |
| 732 | break; |
| 733 | case DataLocation::Storage: |
| 734 | { |
| 735 | if (_keepReference) |
| 736 | m_context << Instruction::DUP2; |
| 737 | else |
| 738 | m_context << Instruction::SWAP1; |
| 739 | // stack: [<base_ref>] <index> <base_ref> |
| 740 | |
| 741 | evmasm::AssemblyItem endTag = m_context.newTag(); |
| 742 | if (_arrayType.isByteArrayOrString()) |
| 743 | { |
| 744 | // Special case of short byte arrays. |
| 745 | m_context << Instruction::SWAP1; |
| 746 | m_context << Instruction::DUP2 << Instruction::SLOAD; |
| 747 | m_context << u256(1) << Instruction::AND << Instruction::ISZERO; |
no test coverage detected