mirror of
https://github.com/syoyo/tinygltf.git
synced 2026-06-08 11:13:50 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a434ee0206 | ||
|
|
7c257a60e3 | ||
|
|
3986f89de0 | ||
|
|
fd365dddab | ||
|
|
a4b5752b1b |
92
.github/instructions/copilot-instructions.md
vendored
92
.github/instructions/copilot-instructions.md
vendored
@@ -1,92 +0,0 @@
|
||||
# Copilot Review Instructions for TinyGLTF
|
||||
|
||||
This document provides guidelines for reviewing code changes in the TinyGLTF repository.
|
||||
|
||||
## Memory Safety
|
||||
|
||||
- **Buffer Overflows**: Check for proper bounds checking when accessing arrays, vectors, and buffers. Verify that buffer sizes are validated before read/write operations.
|
||||
- **Null Pointer Dereferences**: Ensure all pointers are checked for null before dereferencing, especially when handling optional glTF fields.
|
||||
- **Memory Leaks**: Verify proper resource management, including RAII patterns for file handles, image data, and dynamically allocated memory.
|
||||
- **Use-After-Free**: Check for proper lifetime management of objects, especially when dealing with callbacks and asynchronous operations.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- **File I/O**: Verify that all file operations have proper error checking and meaningful error messages.
|
||||
- **JSON Parsing**: Ensure JSON parsing errors are caught and reported with helpful context about the location and nature of the error.
|
||||
- **Resource Loading**: Check that failures in loading images, buffers, and other resources are properly handled and don't cause crashes.
|
||||
- **Error Propagation**: Verify that errors are properly propagated through the call stack with appropriate error messages.
|
||||
|
||||
## glTF 2.0 Specification Compliance
|
||||
|
||||
- **Required Fields**: Ensure all required glTF fields are validated and present.
|
||||
- **Data Types**: Verify that data types match the glTF specification (e.g., component types, accessor types).
|
||||
- **Constraints**: Check that glTF constraints are enforced (e.g., valid ranges for enums, buffer stride requirements).
|
||||
- **Extensions**: Verify proper handling of glTF extensions and that unknown extensions are handled gracefully.
|
||||
- **Validation**: Ensure new features align with the glTF 2.0 specification from the Khronos Group.
|
||||
|
||||
## Cross-Platform Compatibility
|
||||
|
||||
- **Windows**: Check for proper handling of Windows-specific issues (path separators, line endings, file operations).
|
||||
- **Linux**: Verify compatibility with various Linux distributions and compilers (GCC, Clang).
|
||||
- **macOS**: Ensure macOS-specific considerations are addressed (case-sensitive filesystems, Clang compatibility).
|
||||
- **Mobile Platforms**: Consider Android and iOS compatibility where applicable.
|
||||
- **Endianness**: Verify proper handling of byte order when reading binary data.
|
||||
- **Compiler Compatibility**: Ensure code compiles with C++11 standard and supported compilers (MSVC, GCC, Clang).
|
||||
|
||||
## Edge Cases in glTF Parsing
|
||||
|
||||
- **Empty/Minimal Files**: Verify handling of minimal valid glTF files.
|
||||
- **Large Files**: Check for proper handling of large glTF files and buffers without memory exhaustion.
|
||||
- **Malformed Data**: Ensure graceful handling of malformed or invalid glTF data.
|
||||
- **Missing Optional Fields**: Verify correct behavior when optional glTF fields are absent.
|
||||
- **Edge Values**: Check handling of boundary values (e.g., maximum buffer sizes, extreme floating-point values).
|
||||
- **Base64 Encoding**: Verify proper handling of base64-encoded data URIs and invalid encodings.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
- **API Changes**: Ensure public API changes maintain backwards compatibility or are properly deprecated.
|
||||
- **Breaking Changes**: Flag any breaking changes for major version updates and document migration paths.
|
||||
- **Binary Compatibility**: Consider ABI stability for header-only library changes.
|
||||
- **Default Behavior**: Verify that default behavior of existing functionality remains unchanged.
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- **Parsing Performance**: Check for unnecessary copies, redundant allocations, and inefficient algorithms in parsing logic.
|
||||
- **Memory Usage**: Verify efficient memory usage, especially when loading large glTF files.
|
||||
- **I/O Operations**: Ensure efficient file reading and minimize unnecessary disk access.
|
||||
- **String Operations**: Check for efficient string handling (use of string_view, move semantics).
|
||||
- **STL Usage**: Verify appropriate use of STL containers and algorithms.
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Public API**: Ensure all public functions, classes, and methods have clear documentation comments.
|
||||
- **Parameters**: Verify that function parameters are documented, including expected ranges and constraints.
|
||||
- **Return Values**: Document return values and possible error conditions.
|
||||
- **Examples**: Check that complex features include usage examples.
|
||||
- **Changelog**: Verify that significant changes are documented in release notes or changelog.
|
||||
|
||||
## Testing
|
||||
|
||||
- **Test Coverage**: Ensure new features include appropriate unit tests or integration tests.
|
||||
- **Edge Cases**: Verify that tests cover edge cases and error conditions.
|
||||
- **Cross-Platform Tests**: Check that tests run on all supported platforms.
|
||||
- **Regression Tests**: Ensure bug fixes include regression tests to prevent recurrence.
|
||||
- **Sample Files**: Verify that changes are tested with various valid and invalid glTF sample files.
|
||||
|
||||
## Code Style Consistency
|
||||
|
||||
- **Header-Only Pattern**: Maintain the header-only library structure.
|
||||
- **Naming Conventions**: Follow existing naming conventions (CamelCase for types, snake_case for functions where applicable).
|
||||
- **Formatting**: Adhere to the existing code formatting style (check `.clang-format` if available).
|
||||
- **Include Guards**: Verify proper include guards and header organization.
|
||||
- **Namespace Usage**: Ensure proper use of the `tinygltf` namespace.
|
||||
- **Comments**: Maintain consistent comment style with existing code.
|
||||
- **C++11 Compliance**: Verify that code uses C++11 features appropriately and doesn't require newer standards unless specified.
|
||||
|
||||
## Additional Considerations
|
||||
|
||||
- **Third-Party Dependencies**: Minimize new dependencies; prefer existing dependencies (json.hpp, stb_image).
|
||||
- **Warnings**: Ensure code compiles without warnings on supported compilers.
|
||||
- **const Correctness**: Verify proper use of const for parameters and methods.
|
||||
- **RAII**: Prefer RAII patterns for resource management over manual cleanup.
|
||||
- **noexcept**: Use noexcept appropriately for move constructors and move assignment operators.
|
||||
72
.github/workflows/codeql-analysis.yml
vendored
72
.github/workflows/codeql-analysis.yml
vendored
@@ -1,72 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '21 20 * * 5'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp', 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -70,9 +70,20 @@ imgui.ini
|
||||
*.app
|
||||
|
||||
loader_example
|
||||
# Compiled test binaries (built by tests/Makefile, CMakeLists.txt, meson.build)
|
||||
tests/tester
|
||||
tests/tester_noexcept
|
||||
tests/tester_customjson
|
||||
tests/tester_intensive_customjson
|
||||
tests/tester_v3
|
||||
tests/tester_v3_c
|
||||
tests/tester_v3_c_cpp
|
||||
tests/tester_v3_c_v1port
|
||||
tests/tester_v3_c_v1port_cpp
|
||||
tests/tester_v3_freestanding
|
||||
tests/tester_v3_json_c
|
||||
tests/fuzzer/fuzz_gltf
|
||||
tests/fuzzer/fuzz_gltf_customjson
|
||||
tests/issue-97.gltf
|
||||
tests/issue-261.gltf
|
||||
tests/issue-495-external.gltf
|
||||
|
||||
17
README.md
17
README.md
@@ -19,7 +19,7 @@ v3 is a ground-up rewrite with a C-centric, low-overhead design:
|
||||
- **No RTTI, no exceptions required** — suitable for embedded and game-engine use.
|
||||
- **Opt-in filesystem and image I/O** — `TINYGLTF3_ENABLE_FS` / `TINYGLTF3_ENABLE_STB_IMAGE` are off by default; you control when and how assets are loaded.
|
||||
- **C++20 coroutine facade** (optional, auto-detected). C17/C++17 default.
|
||||
- **Hardened against untrusted input** — URI sanitization, post-parse index-bounds validation (default-on, opt-out via `tg3_parse_options.validate_indices = 0`), strict numeric range checks; exercised by a libFuzzer harness and by a cross-version verifier that compares parsed output against the v1 C++ reference loader. See *Security model* below and the `Security Considerations` block at the top of `tiny_gltf_v3.h`.
|
||||
- **Hardened against untrusted input** — URI sanitization, post-parse index-bounds validation (default-on, opt-out via `tg3_parse_options.validate_indices = 0`), strict numeric range checks; exercised by a libFuzzer harness and by a cross-version verifier that compares parsed output against the v1 C++ reference loader. See the `Security Considerations` block at the top of `tiny_gltf_v3.h`.
|
||||
|
||||
### Quick start (v3)
|
||||
|
||||
@@ -55,21 +55,6 @@ tg3_model_free(&model);
|
||||
tg3_error_stack_free(&errors);
|
||||
```
|
||||
|
||||
### Security model (v3 C runtime)
|
||||
|
||||
The v3 C runtime is built for processing **untrusted glTF/GLB input** (server-side asset pipelines, user uploads, etc.) and ships hardened by default:
|
||||
|
||||
- **URI sanitization** — external buffer/image URIs are rejected before any filesystem call if they are empty, contain NUL bytes, begin with `/` or `\`, look like a Windows drive prefix (`X:`), or contain a `..` segment. Production callers SHOULD still provide a custom `tg3_fs_callbacks.read_file` that confines reads to a known directory (e.g. via `openat` plus a `realpath` prefix check) when the input is attacker-controlled.
|
||||
- **Index bounds validation** — every `int32_t` index field populated from JSON (accessor.bufferView, primitive.indices/material/attributes, scene.nodes[], skin.joints[], animation channel/sampler refs, KHR_audio + MSFT_lod refs, …) is checked after the structural parse. Out-of-range indices produce `TG3_ERR_INVALID_INDEX`. Default `tg3_parse_options.validate_indices = 1`; set to `0` only when you need raw round-trip and have your own validator.
|
||||
- **Buffer/accessor range validation** — declared buffer lengths, bufferView ranges, accessor element spans, sparse accessor spans, component types, and overflow-prone size math are checked before returning a model.
|
||||
- **Strict numeric range checks** — JSON numbers feeding integer fields go through finite/round-trip-validated coercion (`tg3__json_number_to_int32` / `_uint64`). `byteStride` is restricted to 0 or [4, 252].
|
||||
- **Memory budget** — the arena and C JSON parser enforce `TINYGLTF3_MAX_MEMORY_BYTES` by default; `max_single_alloc` and `TINYGLTF3_MAX_STRING_LENGTH` bound individual allocation and string size.
|
||||
- **Opt-in fast paths** — `skip_extras_values` avoids materializing `extras` and unknown extension value trees, and `borrow_input_buffers` lets GLB buffer spans reference caller-owned input bytes instead of copying the BIN chunk.
|
||||
- **Image decoding off by default** — the parser does not decode image bytes; use `tg3_parse_options.images_as_is = 1` to skip any decoder entirely when handling untrusted input.
|
||||
- **Error message lifetime** — error strings on `tg3_error_stack` are arena-allocated and remain valid until `tg3_model_free()`. Read or copy them BEFORE freeing the model.
|
||||
|
||||
See the `Security Considerations` block at the top of `tiny_gltf_v3.h` for the authoritative threat-model summary.
|
||||
|
||||
### Testing & verification
|
||||
|
||||
The v3 C runtime ships with three layers of automated coverage:
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
This project manages CVE assignments exclusively through
|
||||
GitHub Security Advisories.
|
||||
@@ -7059,7 +7059,11 @@ static void SerializeNumberProperty(const std::string &key, T number,
|
||||
detail::JsonAddMember(obj, key.c_str(), detail::json(number));
|
||||
}
|
||||
|
||||
#ifdef TINYGLTF_USE_RAPIDJSON
|
||||
#if defined(TINYGLTF_USE_RAPIDJSON) || defined(TINYGLTF_USE_CUSTOM_JSON)
|
||||
// size_t needs an explicit cast to uint64_t: on platforms where size_t is
|
||||
// neither int64_t nor uint64_t (e.g. macOS ARM64 where it is unsigned long,
|
||||
// or 32-bit targets where it is unsigned int) constructing detail::json
|
||||
// directly from a size_t is an ambiguous overload.
|
||||
template <>
|
||||
void SerializeNumberProperty(const std::string &key, size_t number,
|
||||
detail::json &obj) {
|
||||
|
||||
@@ -250,6 +250,7 @@ static size_t tg3json__itoa(int64_t value, char *buf) {
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
#if !TG3JSON_USE_STDLIB_FPCONV
|
||||
static size_t tg3json__utoa(uint64_t value, char *buf) {
|
||||
char tmp[32];
|
||||
size_t n = 0;
|
||||
@@ -267,6 +268,7 @@ static size_t tg3json__utoa(uint64_t value, char *buf) {
|
||||
buf[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
#endif /* !TG3JSON_USE_STDLIB_FPCONV */
|
||||
|
||||
static uint64_t tg3json__double_bits(double v) {
|
||||
uint64_t bits = 0;
|
||||
@@ -433,6 +435,7 @@ static int tg3json__parse_f64_c(const char *start, const char *end, double *out)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TG3JSON_USE_STDLIB_FPCONV
|
||||
static char *tg3json__write_exp(char *p, int exp10) {
|
||||
char tmp[16];
|
||||
size_t n;
|
||||
@@ -479,6 +482,7 @@ static char *tg3json__format_decimal_digits(char *out, const char *digits,
|
||||
for (i = 0; i < ndigits; ++i) *p++ = digits[i];
|
||||
return p;
|
||||
}
|
||||
#endif /* !TG3JSON_USE_STDLIB_FPCONV */
|
||||
|
||||
static int tg3json__same_f64(double a, double b) {
|
||||
return tg3json__double_bits(a) == tg3json__double_bits(b);
|
||||
@@ -579,6 +583,7 @@ static char *tg3json__dtoa_c(double value, char *buf) {
|
||||
uint64_t bits = tg3json__double_bits(value);
|
||||
int negative = (int)(bits >> 63);
|
||||
uint64_t abits = bits & 0x7fffffffffffffffULL;
|
||||
#if !TG3JSON_USE_STDLIB_FPCONV
|
||||
long double x;
|
||||
int dec_e = 0;
|
||||
char digits[24];
|
||||
@@ -586,6 +591,7 @@ static char *tg3json__dtoa_c(double value, char *buf) {
|
||||
int i;
|
||||
char best[80];
|
||||
size_t best_len;
|
||||
#endif
|
||||
|
||||
if (tg3json__is_nan_bits(bits)) {
|
||||
TINYGLTF_JSON_MEMCPY(buf, "nan", 3);
|
||||
@@ -644,7 +650,7 @@ static char *tg3json__dtoa_c(double value, char *buf) {
|
||||
TINYGLTF_JSON_MEMCPY(buf, shortest, TINYGLTF_JSON_STRLEN(shortest));
|
||||
return buf + TINYGLTF_JSON_STRLEN(shortest);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
|
||||
x = negative ? -(long double)value : (long double)value;
|
||||
while (x >= 1.0e16L) {
|
||||
@@ -708,6 +714,7 @@ static char *tg3json__dtoa_c(double value, char *buf) {
|
||||
}
|
||||
TINYGLTF_JSON_MEMCPY(buf, best, best_len);
|
||||
return buf + best_len;
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct tg3json__parser {
|
||||
|
||||
Reference in New Issue
Block a user