texture: Implement my own stupid header validation because libpngs dumb one doesnt work for some got dang reason

gosh
This commit is contained in:
Archie Hilton 2024-05-26 21:36:26 +01:00
parent a60def7a02
commit 25087ea6b4
1 changed files with 46 additions and 6 deletions

View File

@ -9,6 +9,11 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <format>
#include <numeric>
#define PNG_HEADER_BYTES_TO_CHECK 8
TextureLoader *TextureLoader::m_instance = NULL; TextureLoader *TextureLoader::m_instance = NULL;
TextureLoader *TextureLoader::get_instance() { TextureLoader *TextureLoader::get_instance() {
@ -39,6 +44,24 @@ Texture *TextureLoader::load_texture(const std::string &path) {
return m_texture_cache.at(path); return m_texture_cache.at(path);
} }
// FIXME: Figure out why png_sig_cmp never worked and replace this garbage
static bool validate_png_sig(
const std::array<std::uint8_t, PNG_HEADER_BYTES_TO_CHECK> &bytes) {
std::array<std::uint8_t, 8> valid_header = {0x89, 0x50, 0x4e, 0x47,
0x0d, 0x0a, 0x1a, 0x0a};
for (size_t i = 0; i < PNG_HEADER_BYTES_TO_CHECK; i++) {
if (bytes[i] != valid_header[i]) {
spdlog::error(
"Byte header mismatch at position {} expected {:x} got {:x}", i,
valid_header[i], bytes[i]);
return false;
}
}
return true;
}
Texture::Texture(const std::string &path) { Texture::Texture(const std::string &path) {
png_uint_32 width = 0, height = 0; png_uint_32 width = 0, height = 0;
int interlace_type = 0, bit_depth = 0, color_type = 0; int interlace_type = 0, bit_depth = 0, color_type = 0;
@ -54,20 +77,37 @@ Texture::Texture(const std::string &path) {
throw std::exception(); throw std::exception();
} }
png_byte header[4] = {0}; std::array<std::uint8_t, PNG_HEADER_BYTES_TO_CHECK> header;
fread(header, 1, 4, fp); fread(header.data(), 1, PNG_HEADER_BYTES_TO_CHECK, fp);
// I'm not sure why this cast has to be there but clangd doesn't like it not // I'm not sure why this cast has to be there but clangd doesn't like it not
// being there... // being there...
// FIXME: for some reason, this fails. // FIXME: for some reason, this fails.
/* if (!validate_png_sig(header)) {
if (!png_sig_cmp(header, 0, 4)) {
spdlog::error("Texture file {} does not appear to be a png file.", path); spdlog::error("Texture file {} does not appear to be a png file.", path);
std::vector<unsigned char> v;
for (size_t i = 0; i < PNG_HEADER_BYTES_TO_CHECK; i++) {
v.emplace_back(header[i]);
}
auto begin = v.begin();
auto end = v.end();
std::string s = "";
s = std::accumulate(begin, end, s,
[](std::string result, unsigned char value) {
result += std::format("{:02x}", value);
return result;
});
spdlog::error("Bytes: {}", s);
throw std::exception(); throw std::exception();
} }
*/
png_structp png_ptr = png_structp png_ptr =
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
@ -77,7 +117,7 @@ Texture::Texture(const std::string &path) {
setjmp(png_jmpbuf(png_ptr)); setjmp(png_jmpbuf(png_ptr));
png_init_io(png_ptr, fp); png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 4); png_set_sig_bytes(png_ptr, PNG_HEADER_BYTES_TO_CHECK);
png_read_png(png_ptr, info_ptr, png_read_png(png_ptr, info_ptr,
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |