| 1392 | } |
| 1393 | |
| 1394 | void |
| 1395 | ktxValidator::validateLevelIndex(validationContext& ctx) |
| 1396 | { |
| 1397 | ktxLevelIndexEntry* levelIndex = new ktxLevelIndexEntry[ctx.levelCount]; |
| 1398 | ctx.inp->read((char *)levelIndex, ctx.levelIndexSize); |
| 1399 | if (ctx.inp->fail()) |
| 1400 | addIssue(logger::eFatal, IOError.FileRead, strerror(errno)); |
| 1401 | else if (ctx.inp->eof()) |
| 1402 | addIssue(logger::eFatal, IOError.UnexpectedEOF); |
| 1403 | |
| 1404 | validateDfd(ctx); |
| 1405 | if (!ctx.pDfd4Format) { |
| 1406 | // VK_FORMAT_UNDEFINED so we have to get info from the actual DFD. |
| 1407 | // Not hugely robust but validateDfd does check known undefineds such |
| 1408 | // as UASTC. |
| 1409 | if (!ctx.extractFormatInfo(ctx.pActualDfd)) { |
| 1410 | addIssue(logger::eError, ValidatorError.DfdValidationFailure); |
| 1411 | } |
| 1412 | } |
| 1413 | |
| 1414 | uint32_t requiredLevelAlignment = ctx.requiredLevelAlignment(); |
| 1415 | size_t expectedOffset = 0; |
| 1416 | size_t lastByteLength = 0; |
| 1417 | switch (ctx.header.supercompressionScheme) { |
| 1418 | case KTX_SS_NONE: |
| 1419 | case KTX_SS_ZSTD: |
| 1420 | expectedOffset = padn(requiredLevelAlignment, ctx.kvDataEndOffset()); |
| 1421 | break; |
| 1422 | case KTX_SS_BASIS_LZ: |
| 1423 | ktxIndexEntry64 sgdIndex = ctx.header.supercompressionGlobalData; |
| 1424 | // No padding here. |
| 1425 | expectedOffset = sgdIndex.byteOffset + sgdIndex.byteLength; |
| 1426 | break; |
| 1427 | } |
| 1428 | expectedOffset = padn(requiredLevelAlignment, expectedOffset); |
| 1429 | // Last mip level is first in the file. Count down so we can check the |
| 1430 | // distance between levels for the UNDEFINED and SUPERCOMPRESSION cases. |
| 1431 | for (int32_t level = ctx.levelCount-1; level >= 0; level--) { |
| 1432 | if (ctx.header.vkFormat != VK_FORMAT_UNDEFINED |
| 1433 | && ctx.header.supercompressionScheme == KTX_SS_NONE) { |
| 1434 | ktx_size_t actualUBL = levelIndex[level].uncompressedByteLength; |
| 1435 | ktx_size_t expectedUBL = ctx.calcLevelSize(level); |
| 1436 | if (actualUBL != expectedUBL) |
| 1437 | addIssue(logger::eError, |
| 1438 | LevelIndex.IncorrectUncompressedByteLength, |
| 1439 | level, actualUBL, expectedUBL); |
| 1440 | |
| 1441 | if (levelIndex[level].byteLength != |
| 1442 | levelIndex[level].uncompressedByteLength) |
| 1443 | addIssue(logger::eError, LevelIndex.UnequalByteLengths, level); |
| 1444 | |
| 1445 | ktx_size_t expectedByteOffset = ctx.calcLevelOffset(level); |
| 1446 | ktx_size_t actualByteOffset = levelIndex[level].byteOffset; |
| 1447 | if (actualByteOffset != expectedByteOffset) { |
| 1448 | if (actualByteOffset % requiredLevelAlignment != 0) |
| 1449 | addIssue(logger::eError, LevelIndex.UnalignedOffset, |
| 1450 | level, requiredLevelAlignment); |
| 1451 | if (levelIndex[level].byteOffset > expectedByteOffset) |
nothing calls this directly
no test coverage detected