|
25 | 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
26 | 26 | // THE SOFTWARE.
|
27 | 27 |
|
28 |
| -// Version: - v2.8.18 |
| 28 | +// Version: - v2.8.20 |
29 | 29 | // See https://github.com/syoyo/tinygltf/releases for release history.
|
30 | 30 | //
|
31 | 31 | // Tiny glTF loader is using following third party libraries:
|
@@ -6652,7 +6652,7 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
|
6652 | 6652 |
|
6653 | 6653 | memcpy(&version, bytes + 4, 4);
|
6654 | 6654 | swap4(&version);
|
6655 |
| - memcpy(&length, bytes + 8, 4); |
| 6655 | + memcpy(&length, bytes + 8, 4); // Total glb size, including header and all chunks. |
6656 | 6656 | swap4(&length);
|
6657 | 6657 | memcpy(&chunk0_length, bytes + 12, 4); // JSON data length
|
6658 | 6658 | swap4(&chunk0_length);
|
@@ -6708,68 +6708,86 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
|
6708 | 6708 | bin_size_ = 0;
|
6709 | 6709 | } else {
|
6710 | 6710 | // Read Chunk1 info(BIN data)
|
6711 |
| - // At least Chunk1 should have 12 bytes(8 bytes(header) + 4 bytes(bin |
6712 |
| - // payload could be 1~3 bytes, but need to be aligned to 4 bytes) |
6713 |
| - if ((header_and_json_size + 12ull) > uint64_t(length)) { |
| 6711 | + // |
| 6712 | + // issue-440: |
| 6713 | + // 'SHOULD' in glTF spec means 'RECOMMENDED', |
| 6714 | + // So there is a situation that Chunk1(BIN) is composed of zero-sized BIN data |
| 6715 | + // (chunksize(0) + binformat(BIN) = 8bytes). |
| 6716 | + // |
| 6717 | + if ((header_and_json_size + 8ull) > uint64_t(length)) { |
6714 | 6718 | if (err) {
|
6715 | 6719 | (*err) =
|
6716 | 6720 | "Insufficient storage space for Chunk1(BIN data). At least Chunk1 "
|
6717 |
| - "Must have 4 or more bytes, but got " + |
| 6721 | + "Must have 8 or more bytes, but got " + |
6718 | 6722 | std::to_string((header_and_json_size + 8ull) - uint64_t(length)) +
|
6719 | 6723 | ".\n";
|
6720 | 6724 | }
|
6721 | 6725 | return false;
|
6722 | 6726 | }
|
6723 | 6727 |
|
6724 |
| - unsigned int chunk1_length; // 4 bytes |
6725 |
| - unsigned int chunk1_format; // 4 bytes; |
| 6728 | + unsigned int chunk1_length{0}; // 4 bytes |
| 6729 | + unsigned int chunk1_format{0}; // 4 bytes; |
6726 | 6730 | memcpy(&chunk1_length, bytes + header_and_json_size,
|
6727 |
| - 4); // JSON data length |
| 6731 | + 4); // Bin data length |
6728 | 6732 | swap4(&chunk1_length);
|
6729 | 6733 | memcpy(&chunk1_format, bytes + header_and_json_size + 4, 4);
|
6730 | 6734 | swap4(&chunk1_format);
|
6731 | 6735 |
|
6732 |
| - // std::cout << "chunk1_length = " << chunk1_length << "\n"; |
6733 |
| - |
6734 |
| - if (chunk1_length < 4) { |
| 6736 | + if (chunk1_format != 0x004e4942) { |
6735 | 6737 | if (err) {
|
6736 |
| - (*err) = "Insufficient Chunk1(BIN) data size."; |
| 6738 | + (*err) = "Invalid chunkType for Chunk1."; |
6737 | 6739 | }
|
6738 | 6740 | return false;
|
6739 | 6741 | }
|
6740 | 6742 |
|
6741 |
| - if ((chunk1_length % 4) != 0) { |
6742 |
| - if (strictness_==ParseStrictness::Permissive) { |
6743 |
| - if (warn) { |
6744 |
| - (*warn) += "BIN Chunk end is not aligned to a 4-byte boundary.\n"; |
| 6743 | + if (chunk1_length == 0) { |
| 6744 | + |
| 6745 | + if (header_and_json_size + 8 > uint64_t(length)) { |
| 6746 | + if (err) { |
| 6747 | + (*err) = "BIN Chunk header location exceeds the GLB size."; |
6745 | 6748 | }
|
| 6749 | + return false; |
6746 | 6750 | }
|
6747 |
| - else { |
| 6751 | + |
| 6752 | + bin_data_ = nullptr; |
| 6753 | + |
| 6754 | + } else { |
| 6755 | + |
| 6756 | + // When BIN chunk size is not zero, at least Chunk1 should have 12 bytes(8 bytes(header) + 4 bytes(bin |
| 6757 | + // payload could be 1~3 bytes, but need to be aligned to 4 bytes) |
| 6758 | + |
| 6759 | + if (chunk1_length < 4) { |
6748 | 6760 | if (err) {
|
6749 |
| - (*err) = "BIN Chunk end is not aligned to a 4-byte boundary."; |
| 6761 | + (*err) = "Insufficient Chunk1(BIN) data size."; |
6750 | 6762 | }
|
6751 | 6763 | return false;
|
6752 | 6764 | }
|
6753 |
| - } |
6754 | 6765 |
|
6755 |
| - if (uint64_t(chunk1_length) + header_and_json_size > uint64_t(length)) { |
6756 |
| - if (err) { |
6757 |
| - (*err) = "BIN Chunk data length exceeds the GLB size."; |
| 6766 | + if ((chunk1_length % 4) != 0) { |
| 6767 | + if (strictness_==ParseStrictness::Permissive) { |
| 6768 | + if (warn) { |
| 6769 | + (*warn) += "BIN Chunk end is not aligned to a 4-byte boundary.\n"; |
| 6770 | + } |
| 6771 | + } |
| 6772 | + else { |
| 6773 | + if (err) { |
| 6774 | + (*err) = "BIN Chunk end is not aligned to a 4-byte boundary."; |
| 6775 | + } |
| 6776 | + return false; |
| 6777 | + } |
6758 | 6778 | }
|
6759 |
| - return false; |
6760 |
| - } |
6761 | 6779 |
|
6762 |
| - if (chunk1_format != 0x004e4942) { |
6763 |
| - if (err) { |
6764 |
| - (*err) = "Invalid type for chunk1 data."; |
| 6780 | + // +8 chunk1 header size. |
| 6781 | + if (uint64_t(chunk1_length) + header_and_json_size + 8 > uint64_t(length)) { |
| 6782 | + if (err) { |
| 6783 | + (*err) = "BIN Chunk data length exceeds the GLB size."; |
| 6784 | + } |
| 6785 | + return false; |
6765 | 6786 | }
|
6766 |
| - return false; |
6767 |
| - } |
6768 |
| - |
6769 |
| - // std::cout << "chunk1_length = " << chunk1_length << "\n"; |
6770 | 6787 |
|
6771 |
| - bin_data_ = bytes + header_and_json_size + |
6772 |
| - 8; // 4 bytes (bin_buffer_length) + 4 bytes(bin_buffer_format) |
| 6788 | + bin_data_ = bytes + header_and_json_size + |
| 6789 | + 8; // 4 bytes (bin_buffer_length) + 4 bytes(bin_buffer_format) |
| 6790 | + } |
6773 | 6791 |
|
6774 | 6792 | bin_size_ = size_t(chunk1_length);
|
6775 | 6793 | }
|
|
0 commit comments