From 94ca0ab79e8ed53d854b6c6debaea2942d610b51 Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 23 Jan 2025 21:17:30 +0000 Subject: [PATCH] fix: loading of base64 data from gltf files --- src/Crypto/Impl/Base64.cpp | 25 +++++++++++++++++-- src/Crypto/Impl/Base64.h | 1 + .../XModel/Gltf/Internal/GltfBuffer.cpp | 5 ++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Crypto/Impl/Base64.cpp b/src/Crypto/Impl/Base64.cpp index f4400d6a..77d1717f 100644 --- a/src/Crypto/Impl/Base64.cpp +++ b/src/Crypto/Impl/Base64.cpp @@ -32,7 +32,8 @@ namespace base64 size_t DecodeBase64(const void* base64Data, const size_t inputLength, void* outputBuffer, const size_t outputBufferSize) { - unsigned long outLength = GetBase64DecodeOutputLength(inputLength); + unsigned long outLength = GetBase64DecodeOutputLength(base64Data, inputLength); + assert(outLength <= outputBufferSize); if (outLength > outputBufferSize) return 0u; @@ -42,8 +43,28 @@ namespace base64 return static_cast(outLength); } + size_t GetBase64DecodeOutputLength(const void* base64Data, const size_t inputLength) + { + assert(base64Data); + assert(inputLength); + + if (!base64Data || inputLength == 0u) + return 0u; + + auto padding = 0u; + if (inputLength >= 1 && static_cast(base64Data)[inputLength - 1] == '=') + { + if (inputLength >= 2 && static_cast(base64Data)[inputLength - 2] == '=') + padding = 2u; + else + padding = 1u; + } + + return ((inputLength / 4u) * 3u) - padding; + } + size_t GetBase64DecodeOutputLength(const size_t inputLength) { - return inputLength / 4u; + return (inputLength / 4u) * 3u; } } // namespace base64 diff --git a/src/Crypto/Impl/Base64.h b/src/Crypto/Impl/Base64.h index 1e1ec51d..8264a8c3 100644 --- a/src/Crypto/Impl/Base64.h +++ b/src/Crypto/Impl/Base64.h @@ -8,5 +8,6 @@ namespace base64 size_t GetBase64EncodeOutputLength(size_t inputLength); size_t DecodeBase64(const void* base64Data, size_t inputLength, void* outputBuffer, size_t outputBufferSize); + size_t GetBase64DecodeOutputLength(const void* base64Data, const size_t inputLength); size_t GetBase64DecodeOutputLength(size_t inputLength); } // namespace base64 diff --git a/src/ObjLoading/XModel/Gltf/Internal/GltfBuffer.cpp b/src/ObjLoading/XModel/Gltf/Internal/GltfBuffer.cpp index a0edf7f0..fcca640b 100644 --- a/src/ObjLoading/XModel/Gltf/Internal/GltfBuffer.cpp +++ b/src/ObjLoading/XModel/Gltf/Internal/GltfBuffer.cpp @@ -48,11 +48,12 @@ bool DataUriBuffer::ReadDataFromUri(const std::string& uri) if (!IsDataUri(uri)) return false; + const auto base64Data = &uri[URI_PREFIX_LENGTH]; const auto base64DataLength = uri.size() - URI_PREFIX_LENGTH; - m_data_size = base64::GetBase64DecodeOutputLength(base64DataLength); + m_data_size = base64::GetBase64DecodeOutputLength(base64Data, base64DataLength); m_data = std::make_unique(m_data_size); - m_data_size = base64::DecodeBase64(&uri[URI_PREFIX_LENGTH], base64DataLength, m_data.get(), m_data_size); + m_data_size = base64::DecodeBase64(base64Data, base64DataLength, m_data.get(), m_data_size); return m_data_size > 0; }