| 771 | } |
| 772 | |
| 773 | void ValidationContext::validateDFD() { |
| 774 | const auto dfdByteOffset = header.dataFormatDescriptor.byteOffset; |
| 775 | const auto dfdByteLength = header.dataFormatDescriptor.byteLength; |
| 776 | |
| 777 | if (dfdByteOffset == 0 || dfdByteLength == 0) |
| 778 | return; // There is no DFD block |
| 779 | |
| 780 | const auto buffer = std::make_unique<uint8_t[]>(dfdByteLength); |
| 781 | read(dfdByteOffset, buffer.get(), dfdByteLength, "the DFD"); |
| 782 | const auto* ptrDFD = buffer.get(); |
| 783 | const auto* ptrDFDEnd = ptrDFD + dfdByteLength; |
| 784 | const auto* ptrDFDIt = ptrDFD; |
| 785 | |
| 786 | uint32_t dfdTotalSize; |
| 787 | std::memcpy(&dfdTotalSize, ptrDFDIt, sizeof(uint32_t)); |
| 788 | ptrDFDIt += sizeof(uint32_t); |
| 789 | |
| 790 | if (dfdByteLength != dfdTotalSize) |
| 791 | error(DFD::SizeMismatch, dfdByteLength, dfdTotalSize); |
| 792 | |
| 793 | uint32_t numBlocks = 0; |
| 794 | bool foundBDFD = false; |
| 795 | |
| 796 | while (ptrDFDIt < ptrDFDEnd) { |
| 797 | const auto remainingDFDBytes = static_cast<std::size_t>(ptrDFDEnd - ptrDFDIt); |
| 798 | |
| 799 | if (++numBlocks > MAX_NUM_DFD_BLOCKS) { |
| 800 | warning(DFD::TooManyDFDBlocks, numBlocks, remainingDFDBytes); |
| 801 | break; |
| 802 | } |
| 803 | |
| 804 | DFDHeader blockHeader{}; |
| 805 | if (remainingDFDBytes < sizeof(DFDHeader)) { |
| 806 | error(DFD::NotEnoughDataForBlockHeader, remainingDFDBytes); |
| 807 | break; |
| 808 | } |
| 809 | |
| 810 | std::memcpy(&blockHeader, ptrDFDIt, sizeof(DFDHeader)); |
| 811 | |
| 812 | if (blockHeader.descriptorBlockSize < sizeof(DFDHeader)) { |
| 813 | error(DFD::DescriptorBlockSizeTooSmall, numBlocks, +blockHeader.descriptorBlockSize); |
| 814 | |
| 815 | } else if (blockHeader.descriptorBlockSize > remainingDFDBytes) { |
| 816 | error(DFD::DescriptorBlockSizeTooBig, numBlocks, +blockHeader.descriptorBlockSize, remainingDFDBytes); |
| 817 | |
| 818 | } else { |
| 819 | if (blockHeader.vendorId == KHR_DF_VENDORID_KHRONOS && blockHeader.descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT) { |
| 820 | if (std::exchange(foundBDFD, true)) { |
| 821 | warning(DFD::MultipleBDFD, numBlocks); |
| 822 | |
| 823 | } else if (blockHeader.descriptorBlockSize < sizeof(BDFD)) { |
| 824 | error(DFD::BasicDescriptorBlockSizeTooSmall, numBlocks, +blockHeader.descriptorBlockSize); |
| 825 | |
| 826 | } else if (numBlocks != 1) { |
| 827 | // The Basic DFD block has to be the first block. |
| 828 | foundBDFD = false; |
| 829 | |
| 830 | } else { |