diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 2b4f28b..0a7feb5 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -66,10 +66,12 @@ jobs: mkdir build cd build cmake --help - cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On .. + cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On -DTINYGLTF_BUILD_TESTS=ON .. cd .. - name: Build run: cmake --build build --config Release + - name: Run tests + run: ctest --test-dir build -C Release --output-on-failure build-linux: @@ -109,6 +111,12 @@ jobs: cc -I../ -std=c11 -g -O0 -DTINYGLTF3_ENABLE_FS \ -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c ./tester_v3_c_v1port + cc -I../ -std=c11 -g -O0 \ + -o tester_v3_json_c tester_v3_json_c.c + ./tester_v3_json_c + cc -I../ -std=c11 -ffreestanding -g -O0 \ + -o tester_v3_freestanding tester_v3_freestanding.c + ./tester_v3_freestanding cd .. @@ -177,4 +185,3 @@ jobs: git clone https://github.com/Tencent/rapidjson clang++ -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -g -O0 -o loader_example loader_example.cc - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3accbee..3fdcac2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@v5 - name: Configure - run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON + run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON - name: Build run: cmake --build build @@ -53,7 +53,7 @@ jobs: - name: Configure run: | - cmake -B build -DCMAKE_C_COMPILER=clang-21 -DCMAKE_CXX_COMPILER=clang++-21 -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON + cmake -B build -DCMAKE_C_COMPILER=clang-21 -DCMAKE_CXX_COMPILER=clang++-21 -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON - name: Build run: cmake --build build @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@v5 - name: Configure - run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON + run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON - name: Build run: cmake --build build @@ -94,7 +94,7 @@ jobs: uses: actions/checkout@v5 - name: Configure - run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON + run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON - name: Build run: cmake --build build @@ -117,7 +117,7 @@ jobs: run: | mkdir build cd build - cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off .. + cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off -DTINYGLTF_BUILD_TESTS=ON .. - name: Build run: cmake --build build --config Release @@ -141,7 +141,7 @@ jobs: run: | mkdir build cd build - cmake -G "Visual Studio 17 2022" -A Win32 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off .. + cmake -G "Visual Studio 17 2022" -A Win32 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off -DTINYGLTF_BUILD_TESTS=ON .. - name: Build run: cmake --build build --config Release @@ -189,7 +189,7 @@ jobs: - name: Build with CMake run: | - cmake -G"Ninja" -S . -B build + cmake -G"Ninja" -S . -B build -DTINYGLTF_BUILD_TESTS=ON cmake --build build - name: Run loader_example @@ -249,7 +249,7 @@ jobs: - name: Build with CMake Header-Only run: | mkdir build - cmake -B build -DTINYGLTF_HEADER_ONLY=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON + cmake -B build -DTINYGLTF_HEADER_ONLY=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON cmake --build build - name: Run loader_example @@ -259,6 +259,30 @@ jobs: - name: Run tests run: ctest --test-dir build --output-on-failure + # v3 C tests through Meson on the primary desktop platforms. + v3-c-meson: + runs-on: ${{ matrix.os }} + name: v3 C Meson (${{ matrix.os }}) + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Install Meson + run: python -m pip install meson ninja + + - name: Configure + run: meson setup build-meson -Dtests=true + + - name: Build + run: meson compile -C build-meson + + - name: Run v3 C tests + run: meson test -C build-meson --print-errorlogs + # Special Configuration: RapidJSON Backend linux-rapidjson: runs-on: ubuntu-latest @@ -273,7 +297,7 @@ jobs: - name: Configure run: | - cmake -B build -DTINYGLTF_USE_RAPIDJSON=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DCMAKE_PREFIX_PATH=$PWD/rapidjson + cmake -B build -DTINYGLTF_USE_RAPIDJSON=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON -DCMAKE_PREFIX_PATH=$PWD/rapidjson - name: Build run: cmake --build build diff --git a/.github/workflows/mingw-w64-msys2.yml b/.github/workflows/mingw-w64-msys2.yml index 5645d76..a1bc9b4 100644 --- a/.github/workflows/mingw-w64-msys2.yml +++ b/.github/workflows/mingw-w64-msys2.yml @@ -7,7 +7,11 @@ on: - devel paths: - 'tiny_gltf.*' + - 'tinygltf_json_c.h' - 'CMakeLists.txt' + - 'meson.build' + - 'meson_options.txt' + - 'tests/tester_v3*.c' - '.github/workflows/mingw-w64-msys2.yml' pull_request: workflow_dispatch: @@ -37,9 +41,13 @@ jobs: cmake \ -G"Ninja" \ -S . \ - -B build + -B build \ + -DTINYGLTF_BUILD_TESTS=ON - name: Build run: | cmake --build build + - name: Run tests + run: | + ctest --test-dir build --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d9248d..68b7e90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,21 @@ endif (TINYGLTF_BUILD_BUILDER_EXAMPLE) if (TINYGLTF_BUILD_TESTS) enable_testing() + + function(add_tinygltf_v3_c_test target) + add_executable(${target} ${ARGN}) + target_include_directories(${target} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/tests + ) + set_target_properties(${target} PROPERTIES + C_STANDARD 11 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF + ) + add_test(NAME ${target} COMMAND ${target} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) + endfunction() + add_executable(tester tests/tester.cc) target_include_directories(tester PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} @@ -66,62 +81,18 @@ if (TINYGLTF_BUILD_TESTS) target_compile_definitions(tester_intensive_customjson PRIVATE TINYGLTF_USE_CUSTOM_JSON) add_test(NAME tester_intensive_customjson COMMAND tester_intensive_customjson WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) - add_executable(tester_v3_c - tests/tester_v3_c.c - tiny_gltf_v3.c - ) - target_include_directories(tester_v3_c PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/tests - ) - set_target_properties(tester_v3_c PROPERTIES - C_STANDARD 11 - C_STANDARD_REQUIRED ON - C_EXTENSIONS OFF - ) + add_tinygltf_v3_c_test(tester_v3_c tests/tester_v3_c.c tiny_gltf_v3.c) target_compile_definitions(tester_v3_c PRIVATE TINYGLTF3_ENABLE_FS) - add_test(NAME tester_v3_c COMMAND tester_v3_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) - add_executable(tester_v3_c_v1port - tests/tester_v3_c_v1port.c - tiny_gltf_v3.c - ) - target_include_directories(tester_v3_c_v1port PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/tests - ) - set_target_properties(tester_v3_c_v1port PROPERTIES - C_STANDARD 11 - C_STANDARD_REQUIRED ON - C_EXTENSIONS OFF - ) + add_tinygltf_v3_c_test(tester_v3_c_v1port tests/tester_v3_c_v1port.c tiny_gltf_v3.c) target_compile_definitions(tester_v3_c_v1port PRIVATE TINYGLTF3_ENABLE_FS) - add_test(NAME tester_v3_c_v1port COMMAND tester_v3_c_v1port WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) - add_executable(tester_v3_json_c tests/tester_v3_json_c.c) - target_include_directories(tester_v3_json_c PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ) - set_target_properties(tester_v3_json_c PROPERTIES - C_STANDARD 11 - C_STANDARD_REQUIRED ON - C_EXTENSIONS OFF - ) - add_test(NAME tester_v3_json_c COMMAND tester_v3_json_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) + add_tinygltf_v3_c_test(tester_v3_json_c tests/tester_v3_json_c.c) - add_executable(tester_v3_freestanding tests/tester_v3_freestanding.c) - target_include_directories(tester_v3_freestanding PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ) - set_target_properties(tester_v3_freestanding PROPERTIES - C_STANDARD 11 - C_STANDARD_REQUIRED ON - C_EXTENSIONS OFF - ) + add_tinygltf_v3_c_test(tester_v3_freestanding tests/tester_v3_freestanding.c) if (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU") target_compile_options(tester_v3_freestanding PRIVATE -ffreestanding) endif() - add_test(NAME tester_v3_freestanding COMMAND tester_v3_freestanding WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) endif (TINYGLTF_BUILD_TESTS) # diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..f6336bd --- /dev/null +++ b/meson.build @@ -0,0 +1,52 @@ +project( + 'tinygltf', + 'c', + default_options: ['c_std=c11'], + meson_version: '>=0.55.0', +) + +tinygltf_inc = include_directories('.', 'tests') + +if get_option('tests') + tests_workdir = join_paths(meson.current_source_dir(), 'tests') + cc = meson.get_compiler('c') + + tester_v3_c = executable( + 'tester_v3_c', + ['tests/tester_v3_c.c', 'tiny_gltf_v3.c'], + include_directories: tinygltf_inc, + c_args: ['-DTINYGLTF3_ENABLE_FS'], + install: false, + ) + test('tester_v3_c', tester_v3_c, workdir: tests_workdir) + + tester_v3_c_v1port = executable( + 'tester_v3_c_v1port', + ['tests/tester_v3_c_v1port.c', 'tiny_gltf_v3.c'], + include_directories: tinygltf_inc, + c_args: ['-DTINYGLTF3_ENABLE_FS'], + install: false, + ) + test('tester_v3_c_v1port', tester_v3_c_v1port, workdir: tests_workdir) + + tester_v3_json_c = executable( + 'tester_v3_json_c', + 'tests/tester_v3_json_c.c', + include_directories: tinygltf_inc, + install: false, + ) + test('tester_v3_json_c', tester_v3_json_c, workdir: tests_workdir) + + freestanding_args = [] + if cc.get_id() in ['clang', 'gcc'] + freestanding_args += ['-ffreestanding'] + endif + tester_v3_freestanding = executable( + 'tester_v3_freestanding', + 'tests/tester_v3_freestanding.c', + include_directories: tinygltf_inc, + c_args: freestanding_args, + install: false, + ) + test('tester_v3_freestanding', tester_v3_freestanding, workdir: tests_workdir) +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..7f6e95a --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('tests', type: 'boolean', value: true, description: 'Build and run tinygltf tests') diff --git a/tests/tester_v3_c.c b/tests/tester_v3_c.c index 4e21a52..c85ac70 100644 --- a/tests/tester_v3_c.c +++ b/tests/tester_v3_c.c @@ -1372,6 +1372,255 @@ static int check_borrow_input_buffers(void) { return ok; } +static int parse_path_for_test(tg3_model *model, tg3_error_stack *errors, + const char *path, const tg3_parse_options *opts) { + FILE *fp; + uint8_t *buf; + long sz; + size_t got; + const char *slash; + uint32_t base_len; + tg3_error_code err; + + memset(model, 0, sizeof(*model)); + fp = fopen(path, "rb"); + if (!fp) { + fprintf(stderr, "open failed: %s\n", path); + return 0; + } + if (fseek(fp, 0, SEEK_END) != 0 || (sz = ftell(fp)) < 0 || + fseek(fp, 0, SEEK_SET) != 0) { + fprintf(stderr, "seek failed: %s\n", path); + fclose(fp); + return 0; + } + buf = (uint8_t *)malloc((size_t)sz); + if (!buf) { + fprintf(stderr, "alloc failed: %s\n", path); + fclose(fp); + return 0; + } + got = fread(buf, 1, (size_t)sz, fp); + fclose(fp); + if (got != (size_t)sz) { + fprintf(stderr, "short read: %s\n", path); + free(buf); + return 0; + } + + slash = strrchr(path, '/'); + base_len = slash ? (uint32_t)(slash - path) : 0; + err = tg3_parse_auto(model, errors, buf, (uint64_t)sz, path, base_len, opts); + free(buf); + if (err != TG3_OK) { + fprintf(stderr, "parse failed: %s err=%d\n", path, (int)err); + return 0; + } + return 1; +} + +static int has_str(const tg3_str *items, uint32_t count, const char *needle) { + uint32_t i; + for (i = 0; i < count; ++i) { + if (tg3_str_equals_cstr(items[i], needle)) return 1; + } + return 0; +} + +static int ext_has(const tg3_extras_ext *ext, const char *name) { + uint32_t i; + if (!ext || !ext->extensions) return 0; + for (i = 0; i < ext->extensions_count; ++i) { + if (tg3_str_equals_cstr(ext->extensions[i].name, name)) return 1; + } + return 0; +} + +static int check_stdio_parse_regression_files(void) { + tg3_model model; + tg3_error_stack errors; + tg3_parse_options opts; + int ok = 1; + + tg3_parse_options_init(&opts); + + tg3_error_stack_init(&errors); + if (!parse_path_for_test(&model, &errors, "../models/Extensions-issue97/test.gltf", &opts) || + model.extensions_used_count != 1 || + !has_str(model.extensions_used, model.extensions_used_count, + "VENDOR_material_some_ext") || + model.materials_count != 1 || + !ext_has(&model.materials[0].ext, "VENDOR_material_some_ext")) { + fprintf(stderr, "issue-97 extension parse regression failed\n"); + ok = 0; + } + tg3_model_free(&model); + tg3_error_stack_free(&errors); + if (!ok) return 0; + + tg3_error_stack_init(&errors); + if (!parse_path_for_test(&model, &errors, + "../models/Extensions-overwrite-issue261/issue-261.gltf", + &opts) || + !has_str(model.extensions_used, model.extensions_used_count, + "KHR_lights_punctual") || + !ext_has(&model.ext, "NV_MDL") || + !ext_has(&model.ext, "KHR_lights_punctual")) { + fprintf(stderr, "issue-261 extension overwrite regression failed\n"); + ok = 0; + } + tg3_model_free(&model); + tg3_error_stack_free(&errors); + if (!ok) return 0; + + tg3_error_stack_init(&errors); + if (!parse_path_for_test(&model, &errors, + "../models/regression/unassigned-skeleton.gltf", + &opts) || + model.skins_count != 1 || model.skins[0].skeleton != -1) { + fprintf(stderr, "issue-321 unassigned skeleton regression failed\n"); + ok = 0; + } + tg3_model_free(&model); + tg3_error_stack_free(&errors); + if (!ok) return 0; + + tg3_error_stack_init(&errors); + if (!parse_path_for_test(&model, &errors, + "../models/regression/zero-sized-bin-chunk-issue-440.glb", + &opts)) { + fprintf(stderr, "issue-440 zero-sized BIN chunk regression failed\n"); + ok = 0; + } + tg3_model_free(&model); + tg3_error_stack_free(&errors); + if (!ok) return 0; + + tg3_error_stack_init(&errors); + if (!parse_path_for_test(&model, &errors, "issue-492.glb", &opts)) { + fprintf(stderr, "issue-492 inverse bind matrices regression failed\n"); + ok = 0; + } + tg3_model_free(&model); + tg3_error_stack_free(&errors); + return ok; +} + +static int check_stdio_parse_file_cube(void) { + tg3_model model; + tg3_error_stack errors; + tg3_parse_options opts; + tg3_error_code err; + int ok; + + tg3_error_stack_init(&errors); + tg3_parse_options_init(&opts); + opts.images_as_is = 1; + err = tg3_parse_file(&model, &errors, "../models/Cube/Cube.gltf", 24, &opts); + ok = (err == TG3_OK && model.buffers_count == 1 && + model.buffers[0].data.data && model.buffers[0].data.count > 0 && + model.images_count == 2 && model.images[0].uri.data); + if (!ok) { + fprintf(stderr, "stdio parse_file Cube regression failed: err=%d\n", (int)err); + } + tg3_model_free(&model); + tg3_error_stack_free(&errors); + return ok; +} + +static int write_read_stdio_roundtrip(const uint8_t *json, uint64_t json_size, + const char *path, + int (*check_model)(const tg3_model *model)) { + tg3_model model; + tg3_model roundtrip; + tg3_error_stack errors; + tg3_parse_options parse_opts; + tg3_write_options write_opts; + tg3_error_code err; + int ok = 0; + + tg3_error_stack_init(&errors); + tg3_parse_options_init(&parse_opts); + tg3_write_options_init(&write_opts); + + err = tg3_parse(&model, &errors, json, json_size, "", 0, &parse_opts); + if (err != TG3_OK) { + fprintf(stderr, "stdio write source parse failed: err=%d\n", (int)err); + goto done; + } + err = tg3_write_to_file(&model, &errors, path, (uint32_t)strlen(path), &write_opts); + if (err != TG3_OK) { + fprintf(stderr, "stdio write_to_file failed: %s err=%d\n", path, (int)err); + goto done_model; + } + err = tg3_parse_file(&roundtrip, &errors, path, (uint32_t)strlen(path), &parse_opts); + if (err != TG3_OK) { + fprintf(stderr, "stdio parse_file roundtrip failed: %s err=%d\n", path, (int)err); + goto done_model; + } + ok = check_model(&roundtrip); + tg3_model_free(&roundtrip); + +done_model: + tg3_model_free(&model); +done: + remove(path); + tg3_error_stack_free(&errors); + return ok; +} + +static int check_empty_node_scene_material_model(const tg3_model *model) { + return model->nodes_count == 1 && + model->scenes_count == 1 && + model->materials_count == 1 && + model->scenes[0].nodes_count == 1 && + model->scenes[0].nodes[0] == 0; +} + +static int check_light_lod_model(const tg3_model *model) { + return model->lights_count == 1 && + model->nodes_count == 3 && + model->nodes[0].light == 0 && + model->nodes[0].lods_count == 2 && + model->nodes[0].lods[0] == 1 && + model->nodes[0].lods[1] == 2 && + model->scenes_count == 1 && + model->scenes[0].nodes_count == 1 && + model->scenes[0].nodes[0] == 0; +} + +static int check_stdio_write_regression_cases(void) { + static const uint8_t empty_node_scene_material[] = + "{\"asset\":{\"version\":\"2.0\"}," + "\"nodes\":[{}]," + "\"scenes\":[{\"nodes\":[0]}]," + "\"materials\":[{}]}"; + static const uint8_t light_lod[] = + "{\"asset\":{\"version\":\"2.0\"}," + "\"extensionsUsed\":[\"KHR_lights_punctual\",\"MSFT_lod\"]," + "\"extensions\":{\"KHR_lights_punctual\":{\"lights\":[{" + "\"type\":\"point\",\"intensity\":0.75,\"color\":[1.0,0.8,0.95]}]}}," + "\"nodes\":[{\"extensions\":{\"KHR_lights_punctual\":{\"light\":0}," + "\"MSFT_lod\":{\"ids\":[1,2]}}},{},{}]," + "\"scenes\":[{\"nodes\":[0]}]}"; + + if (!write_read_stdio_roundtrip( + empty_node_scene_material, + (uint64_t)(sizeof(empty_node_scene_material) - 1), + "tg3_v3_empty_node_scene_material.gltf", + check_empty_node_scene_material_model)) { + fprintf(stderr, "empty node/scene/material stdio roundtrip failed\n"); + return 0; + } + if (!write_read_stdio_roundtrip(light_lod, (uint64_t)(sizeof(light_lod) - 1), + "tg3_v3_light_lod.gltf", + check_light_lod_model)) { + fprintf(stderr, "light/lod stdio roundtrip failed\n"); + return 0; + } + return 1; +} + static int parse_file_arg(const char *path) { FILE *fp = fopen(path, "rb"); uint8_t *buf; @@ -1539,5 +1788,14 @@ int main(int argc, char **argv) { if (!check_borrow_input_buffers()) { return 1; } + if (!check_stdio_parse_regression_files()) { + return 1; + } + if (!check_stdio_parse_file_cube()) { + return 1; + } + if (!check_stdio_write_regression_cases()) { + return 1; + } return 0; } diff --git a/tiny_gltf_v3.c b/tiny_gltf_v3.c index d8680df..da515b3 100644 --- a/tiny_gltf_v3.c +++ b/tiny_gltf_v3.c @@ -641,6 +641,15 @@ static int tg3__u64_mul_overflow(uint64_t a, uint64_t b, uint64_t *out) { return 0; } +static int tg3__u64_fits_size(uint64_t v) { +#if SIZE_MAX < UINT64_MAX + return v <= (uint64_t)SIZE_MAX; +#else + (void)v; + return 1; +#endif +} + static int tg3__json_has(const tg3json_value *o, const char *key) { return tg3json_object_get(o, key) ? 1 : 0; } @@ -1254,7 +1263,7 @@ static int tg3__parse_buffer(tg3__parse_ctx *ctx, const tg3json_value *o, tg3__parse_extras_and_extensions(ctx, o, &buf->ext); return 1; } - if (byte_length > (uint64_t)((size_t)-1)) { + if (!tg3__u64_fits_size(byte_length)) { tg3__error_push(ctx->errors, TG3_SEVERITY_ERROR, TG3_ERR_OUT_OF_MEMORY, "buffer.byteLength exceeds addressable size", NULL, -1); return 0; @@ -1287,7 +1296,7 @@ static int tg3__parse_buffer(tg3__parse_ctx *ctx, const tg3json_value *o, uint64_t file_size = 0; if (tg3__load_external_file(ctx, &file_data, &file_size, buf->uri.data, buf->uri.len)) { uint8_t *data = NULL; - if (file_size > (uint64_t)((size_t)-1)) { + if (!tg3__u64_fits_size(file_size)) { tg3__error_push(ctx->errors, TG3_SEVERITY_ERROR, TG3_ERR_OUT_OF_MEMORY, "external buffer exceeds addressable size", NULL, -1); if (ctx->opts.fs.free_file) ctx->opts.fs.free_file(file_data, file_size, ctx->opts.fs.user_data);