Commit Graph

1185 Commits

Author SHA1 Message Date
Syoyo Fujita
3a2f149458 Document v3 C security model and verification layers in README
Adds a Security model subsection covering URI sanitization, index-bounds
validation, strict numeric ranges, the 1 GB memory budget, image-decoder
opt-out, and error message lifetime — pointing to the authoritative
Security Considerations block in tiny_gltf_v3.h.

Adds a Testing & verification subsection describing the three coverage
layers shipped with the v3 C runtime: internal regression tests in
tester_v3_c, the cross-version DIGEST verifier in test_runner.py, and
the libFuzzer harness with ASan+UBSan in tests/v3/fuzzer/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:16:30 +09:00
Syoyo Fujita
a8fb48fa91 Harden v3 C parser against untrusted glTF input
Threat model: parser is intended for server-side processing of attacker-
supplied glTF/GLB. Two adversarial review rounds plus a 1-hour libFuzzer
run (4 workers, ASan+UBSan, ~420M execs total, zero new artifacts) drove
this set of fixes. Concrete PoCs in tests/v3/security/ confirmed each
issue was exploitable on the prior code.

Path traversal (CRITICAL): tg3__load_external_file concatenated base_dir
with the JSON-supplied URI verbatim. A glTF with
"uri":"../../../tmp/secret" successfully loaded the file from outside
base_dir (verified by FNV64 match). New tg3__uri_is_safe rejects empty,
NUL, leading / or \\, Windows drive prefixes, and any '..' segment.
Path-buffer length checks switched to saturating subtraction so 32-bit
size_t cannot wrap.

Sign-coercion in byteStride: int32_t -1 was cast directly to uint32_t,
producing 0xFFFFFFFF and propagating into downstream count*stride math.
Restrict to glTF spec range: 0 (tightly packed) or [4, 252].

Index validation: parsed int32 index fields (accessor.bufferView,
primitive.indices/material/attributes, node.mesh/skin/camera/light,
scene.nodes[], skin.joints[], animation channel/sampler refs, MSFT_lod
ids, KHR_audio emitter/source refs, etc.) were stored unchecked. New
tg3__validate_indices walks every index field and returns
TG3_ERR_INVALID_INDEX on out-of-range. Gated by
tg3_parse_options.validate_indices, defaulting to 1.

Use-after-free on parse failure (PRE-EXISTING, surfaced by ASan during
fix verification): tg3_parse and tg3_parse_glb destroyed model->arena_
on error paths, but error messages on the user-facing tg3_error_stack
were arena-allocated. Any caller reading errors.entries[i].message
after parse failure read freed memory. tg3_model_free is now sole arena
owner; arena lives across error paths so messages stay valid until the
caller frees the model.

Other fixes:
- tg3_parse_glb: hoist tg3__model_init before header parse so callers
  can safely tg3_model_free on header failure.
- tg3__parse_primitive morph targets: when arena alloc returns NULL,
  pair with target_counts[ti]=0 so validators do not deref.
- Defensive 'if (!tarr) continue' in the morph-target validator loop.
- New Security Considerations block in tiny_gltf_v3.h documents the
  threat model, default-on validation, fs-callback contract, and error
  message lifetime.

Verification: 13 internal tests in tester_v3_c (incl. 7 new security
regressions covering path traversal absolute and relative, fs-callback
no-call assertion, byteStride wrap, OOB index, opt-in raw mode, ext
fields, and arena-message lifetime), 134/134 Khronos sample models
match v1 ground truth digest, 1-hour ASan+UBSan fuzz on the final code
clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:02:34 +09:00
Syoyo Fujita
188d7b257b Cross-version verifier comparing v3 C parser against v1 ground truth
Adds a structured DIGEST block (asset, buffers w/ FNV-1a hash, bufferViews,
accessors w/ min/max, mesh primitives w/ sorted attribute maps, nodes w/
normalized TRS+matrix, materials, textures/samplers/images, skins,
animations, cameras, scenes) emitted by both loader_example (v1) and
tester_v3_c (v3 C, now accepting a file arg). test_runner.py runs both,
diffs the digests, and reports counts/digest mismatches with v1 as truth.

Also rolls in /simplify follow-ups on top of 7f736d1: a shared
tg3__json_number_to_double helper to dedupe inline number coercions, a
collapsed fuzz_gltf_v3_c harness using a single tg3_fuzz_run dispatcher,
a rewritten max_safe_uint64_real comment explaining the 53-bit mantissa
constraint, and a tests/Makefile fix so tester_v3_c is a real prerequisite
of `all` (built once via the dedicated rule, not duplicated).

Verifier passes 134/134 on the Khronos glTF-Sample-Models/2.0 suite.
bufferView.target and image.mime_type/uri are intentionally excluded from
the digest: v1 infers target from accessor usage and rewrites image
URIs/mime via stb_image, neither of which is a parse-fidelity concern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 11:50:28 +09:00
Syoyo Fujita
7f736d19db Harden v3 numeric parsing and add C fuzz harness
Reject non-finite/out-of-range JSON numbers in int32/uint64 fields and
array/attribute elements instead of silently truncating, initialize the
model on parse-file failure, and free the partial JSON document when the
root is not an object. Adds a pure-C libFuzzer harness (fuzz_gltf_v3_c)
alongside the existing C++ one and tests covering the new failure modes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 04:10:32 +09:00
Syoyo Fujita
af09ec3405 Mark v3 C runtime experimental
Update README.md to describe the pure-C v3 runtime accurately, fix the JSON backend reference, and mark the new C implementation as experimental.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 09:16:14 +09:00
Syoyo Fujita
85441bbe19 Add pure-C TinyGLTF v3 runtime
Introduce a C-first TinyGLTF v3 runtime in tiny_gltf_v3.c with a pure-C JSON backend, hook the public header to the new implementation, and add CMake/test coverage for parse and write round-trips.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 04:28:41 +09:00
Syoyo Fujita
a18f41142f Remove projects section from README
Removed the list of projects using TinyGLTF from the README.
2026-05-04 05:37:00 +09:00
Syoyo Fujita
d8f3bd93f7 add pr template. 2026-04-06 04:43:12 +09:00
Syoyo Fujita
bd6db55b70 Create SECURITY.md 2026-04-06 04:30:19 +09:00
Syoyo Fujita
9422613562 Modify copyright notice in tiny_gltf_v3.h
Updated copyright year and authorship information.
2026-03-25 02:35:54 +09:00
Syoyo Fujita
135695e918 Clarify C++ version requirement in README
Updated README to reflect C++11 requirement and removed outdated information.
v3.0.0
2026-03-24 04:52:36 +09:00
Syoyo Fujita
b163ff225a Merge pull request #537 from syoyo/v3
V3
2026-03-24 04:50:29 +09:00
Syoyo Fujita
1a04c114c6 Merge pull request #544 from syoyo/copilot/sub-pr-537-8bf00c20-87df-4d41-b746-2db2da281b7c
docs: Add v3 API section to README with deprecation notice for v2
2026-03-24 01:49:04 +09:00
copilot-swe-agent[bot]
b5a962f1f4 Add v3 documentation to README.md with summary, quick start, and v2 deprecation notice
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/ffbaa2c3-7ad0-4210-b802-3253f1443ec2
2026-03-23 16:38:16 +00:00
copilot-swe-agent[bot]
f143766625 Initial plan 2026-03-23 16:36:22 +00:00
Syoyo Fujita
1215adc13a Merge pull request #543 from syoyo/copilot/sub-pr-537-please-work
Fix misleading comment on cj_dbl_to_i64 clamping behavior
2026-03-24 01:32:48 +09:00
copilot-swe-agent[bot]
826b71cc24 Remove accidentally committed tmp.glb
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/74f01d98-ca42-4950-984e-458d4e3eeccd
2026-03-21 20:39:39 +00:00
copilot-swe-agent[bot]
dfd94f03fb Fix cj_dbl_to_i64 comment to accurately describe clamping behavior
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/74f01d98-ca42-4950-984e-458d4e3eeccd
2026-03-21 20:39:31 +00:00
copilot-swe-agent[bot]
131c4489fa Initial plan 2026-03-21 20:37:03 +00:00
Syoyo Fujita
9248070755 Merge pull request #536 from syoyo/copilot/implement-gltf-parser-unit-tester
Add intensive parser unit tester and LLVM fuzzer for tinygltf_json.h backend
2026-03-22 05:33:43 +09:00
Syoyo Fujita
d8fb6cad78 Update tests/fuzzer/fuzz_gltf_customjson.cc
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-22 02:50:24 +09:00
Syoyo Fujita
e2e40f58ae Update tests/fuzzer/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-22 02:50:11 +09:00
Syoyo Fujita
306c72fce9 Update tests/tester_intensive_customjson.cc
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-22 02:50:02 +09:00
Syoyo Fujita
594c3a057b Merge pull request #540 from syoyo/copilot/sub-pr-537-another-one
Fix float32_mode mis-classifying long integer tokens as floats
2026-03-21 07:04:36 +09:00
Syoyo Fujita
ad316367b9 Merge pull request #541 from syoyo/copilot/sub-pr-537-yet-again
Fix `tg3__arena_strdup` conflating empty strings with absent strings
2026-03-21 07:04:10 +09:00
Syoyo Fujita
1f15c2d140 Merge pull request #538 from syoyo/copilot/sub-pr-537
Fix tg3_writer allocation: replace calloc/free with new/delete
2026-03-21 06:38:06 +09:00
Syoyo Fujita
1d5e721a24 Merge pull request #542 from syoyo/copilot/sub-pr-537-one-more-time
Guard TINYGLTF3_IMPLEMENTATION against C translation units
2026-03-21 06:37:42 +09:00
copilot-swe-agent[bot]
c9a9b1175a Fix float32_mode integer parsing: preserve int64 precision for integer-only tokens
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/a77fd614-00f3-49c1-bb4a-0498771cc63b
2026-03-20 21:24:37 +00:00
copilot-swe-agent[bot]
5e0c5b9ada Fix tg3__arena_strdup to distinguish empty strings from absent strings
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/445ab61b-4294-45e6-8faf-4f2fc8dfe369
2026-03-20 21:21:35 +00:00
copilot-swe-agent[bot]
03b9db782e Add C++ compilation guard for TINYGLTF3_IMPLEMENTATION
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/9d34bfe8-6b91-44f8-aedc-adb3bfeadf84
2026-03-20 21:21:26 +00:00
Syoyo Fujita
c99e713fab Merge pull request #539 from syoyo/copilot/sub-pr-537-again
Use `__VA_OPT__` for variadic comma elision in C++20, `##__VA_ARGS__` fallback for C++17
2026-03-21 06:19:35 +09:00
copilot-swe-agent[bot]
8c8cbfa0ba Initial plan 2026-03-20 21:15:51 +00:00
copilot-swe-agent[bot]
0949983acc Initial plan 2026-03-20 21:15:45 +00:00
copilot-swe-agent[bot]
c870bd5fd6 Initial plan 2026-03-20 21:15:36 +00:00
copilot-swe-agent[bot]
b76cf7aa21 Replace ##__VA_ARGS__ with portable TG3__COMMA_VA_ARGS helper (C++17/C++20)
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/a7105342-8673-4241-b727-29026461cc67
2026-03-20 20:42:17 +00:00
copilot-swe-agent[bot]
946c5a2d9b Fix tg3_writer allocation: use new/delete instead of calloc/free
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/c2a9ce6c-1c60-4925-b67b-e5ad2ffe1cd2
2026-03-20 20:39:43 +00:00
Syoyo Fujita
f7bd377a69 Update tiny_gltf_v3.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-21 05:36:13 +09:00
Syoyo Fujita
5d6984b9fd Update tiny_gltf_v3.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-21 05:35:53 +09:00
Syoyo Fujita
3331c6cee2 Update tinygltf_json.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-21 05:35:34 +09:00
copilot-swe-agent[bot]
97316e140c Initial plan 2026-03-20 20:35:31 +00:00
copilot-swe-agent[bot]
0e370ef62f Initial plan 2026-03-20 20:34:21 +00:00
Syoyo Fujita
2c7bf2c932 Fix fuzzer-found bugs, add libFuzzer harness for v3
Add tests/v3/fuzzer/ with libFuzzer harness covering all four parse
paths (auto-detect, JSON, GLB, float32 mode) with ASan+UBSan.

Fix two bugs found by 10+ hours of fuzzing (~23M iterations):

1. UB: (int64_t)inf in cj_parse_number when extreme exponents like
   22222222e222222 produce infinity. Add cj_dbl_to_i64() that clamps
   inf/NaN/out-of-range values before casting.

2. Null deref in tg3__parse_string when glTF array elements are not
   JSON objects (e.g. "scenes": [[3]]). Add is_object() validation
   in TG3__PARSE_ARRAY_SIMPLE and TG3__PARSE_ARRAY_IDX macros.

Verified clean: 5.8M additional runs with zero crashes after fixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 04:10:25 +09:00
Syoyo Fujita
2aeac50277 Add fast float parser and benchmark float-heavy scene
Replace strtod() with Clinger's fast path in tinygltf_json.h for ~1.5x
faster JSON float parsing. The new parser accumulates all digits into a
uint64 mantissa and uses exact power-of-10 tables for conversion,
avoiding locale-dependent strtod for ~99% of JSON float values.

Add optional float32 parse mode (parse_float32 option) that parses JSON
floats at single precision — fewer significant digits needed, wider fast
path range. Breaks strict double-precision conformance but sufficient
for glTF data which is typically single-precision.

Benchmark additions:
- gen_synthetic: add float_heavy preset (~500MB ASCII float JSON)
- bench_v3: add --float32 flag for float32 parse mode benchmarking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 09:00:30 +09:00
Syoyo Fujita
78f4a5cfe8 Add tinygltf v3 single-header C API (tiny_gltf_v3.h)
Ground-up C-centric rewrite of tinygltf with pure C POD structs,
arena-based memory management, structured error reporting, streaming
callbacks, and no STL dependency in the public API. Uses tinygltf_json.h
as the sole JSON backend.

Includes complete parser (JSON + GLB), writer (JSON + GLB), streaming
writer, C++ RAII wrappers, and C++20 coroutine facade. Verified with
Cube.gltf and Fox.glb parse/write round-trips.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 03:31:05 +09:00
Syoyo Fujita
aa63297061 Merge branch 'release' of github.com:syoyo/tinygltf into release 2026-03-19 13:39:50 +09:00
Syoyo Fujita
7163d5ab17 ignore build/ 2026-03-19 13:39:37 +09:00
copilot-swe-agent[bot]
12affdcc64 Address code review feedback: .gitignore path, fuzzer docs, trailing whitespace test
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
2026-03-19 00:44:04 +00:00
copilot-swe-agent[bot]
2c1a8be82d Add intensive parser unit tester and LLVM fuzzer for tinygltf_json.h backend
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
2026-03-19 00:42:53 +00:00
copilot-swe-agent[bot]
df3efc6453 Initial plan for intensive parser unit tester and LLVM fuzzer
Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
2026-03-19 00:36:24 +00:00
copilot-swe-agent[bot]
99720ea0cc Initial plan 2026-03-19 00:32:52 +00:00