初始化内容

This commit is contained in:
2026-09-16 14:07:40 +08:00
parent 6934b390bf
commit 4f643c1e7c
18350 changed files with 6088489 additions and 305 deletions
+7
View File
@@ -0,0 +1,7 @@
# Use this for strict compilation check(will work on clang 3.8+)
#EXTRA_CXXFLAGS := -fsanitize=address -Wall -Werror -Weverything -Wno-c++11-long-long -DTINYGLTF_APPLY_CLANG_WEVERYTHING
all: ../tiny_gltf.h
clang++ -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester tester.cc
clang++ -DTINYGLTF_NOEXCEPTION -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester_noexcept tester.cc
clang++ -DTINYGLTF_USE_CUSTOM_JSON -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester_intensive_customjson tester_intensive_customjson.cc
+10445
View File
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
# Fuzzing test
Do fuzzing test for TinyGLTF API.
## Supported API
* [x] LoadASCIIFromString
* [ ] LoadBinaryFromMemory
### Custom JSON backend (`tinygltf_json.h`)
* [x] LoadASCIIFromString
* [x] LoadBinaryFromMemory
## Requirements
* meson
* clang with fuzzer support(`-fsanitize=fuzzer`. at least clang 8.0 should work)
## Setup
### Ubuntu 18.04
```
$ sudo apt install clang++-8
$ sudo apt install libfuzzer-8-dev
```
Optionally, if you didn't set `update-alternatives` you can set `clang++` to point to `clang++8`
```
$ sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-8 10
$ sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 10
```
## How to compile
```
$ CXX=clang++ CC=clang meson build
$ cd build
$ ninja
```
This builds two fuzzers:
* `fuzz_gltf` default nlohmann/json backend
* `fuzz_gltf_customjson` custom `tinygltf_json.h` backend (tests both ASCII and binary parsing paths)
## How to run
Increase memory limit. e.g. `-rss_limit_mb=50000`
```
$ ./fuzz_gltf -rss_limit_mb=20000 -jobs 4
$ ./fuzz_gltf_customjson -rss_limit_mb=20000 -jobs 4
```
+33
View File
@@ -0,0 +1,33 @@
#include <cstdint>
#include <cstring>
#include <memory>
#include <vector>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define TINYGLTF_IMPLEMENTATION
#include "tiny_gltf.h"
static void parse_intCoding4(const uint8_t *data, size_t size)
{
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
const char *str = reinterpret_cast<const char *>(data);
bool ret = ctx.LoadASCIIFromString(&model, &err, &warn, str, size, /* base_dir */"" );
(void)ret;
}
extern "C"
int LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size)
{
parse_intCoding4(data, size);
return 0;
}
+76
View File
@@ -0,0 +1,76 @@
/*
* LLVM libFuzzer harness for tinygltf with the custom JSON backend
* (tinygltf_json.h).
*
* Exercises:
* 1. LoadASCIIFromString glTF JSON parsing
* 2. LoadBinaryFromMemory GLB binary parsing
*
* Build (clang with libFuzzer):
* clang++ -std=c++11 -fsanitize=address,fuzzer \
* -DTINYGLTF_USE_CUSTOM_JSON \
* -I../../ fuzz_gltf_customjson.cc \
* -o fuzz_gltf_customjson
*
* Run:
* ./fuzz_gltf_customjson -rss_limit_mb=20000 -jobs 4
*/
#include <cstdint>
#include <cstring>
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define TINYGLTF_IMPLEMENTATION
#ifndef TINYGLTF_USE_CUSTOM_JSON
#define TINYGLTF_USE_CUSTOM_JSON
#endif
#include "tiny_gltf.h"
/* Fuzz the ASCII (JSON) parser path */
static void fuzz_ascii(const uint8_t *data, size_t size) {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
const char *str = reinterpret_cast<const char *>(data);
bool ret =
ctx.LoadASCIIFromString(&model, &err, &warn, str,
static_cast<unsigned int>(size), /* base_dir */ "");
(void)ret;
}
/* Fuzz the binary (GLB) parser path */
static void fuzz_binary(const uint8_t *data, size_t size) {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
bool ret = ctx.LoadBinaryFromMemory(&model, &err, &warn, data,
static_cast<unsigned int>(size),
/* base_dir */ "");
(void)ret;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size == 0) return 0;
/* Use the lowest bit of the first byte to select the parse path.
* The remaining bits are left for the fuzzer engine to explore;
* additional paths (e.g. LoadASCIIFromFile, check_sections flags)
* can be added here in the future using more selector bits. */
uint8_t selector = data[0];
const uint8_t *payload = data + 1;
size_t payload_size = size - 1;
if (selector & 1) {
fuzz_binary(payload, payload_size);
} else {
fuzz_ascii(payload, payload_size);
}
return 0;
}
+15
View File
@@ -0,0 +1,15 @@
project('fuzz_tinygltf', 'cpp', default_options : ['cpp_std=c++11'])
incdirs = include_directories('../../')
executable('fuzz_gltf',
'fuzz_gltf.cc',
include_directories : incdirs,
cpp_args : '-fsanitize=address,fuzzer',
link_args : '-fsanitize=address,fuzzer' )
executable('fuzz_gltf_customjson',
'fuzz_gltf_customjson.cc',
include_directories : incdirs,
cpp_args : ['-fsanitize=address,fuzzer', '-DTINYGLTF_USE_CUSTOM_JSON'],
link_args : '-fsanitize=address,fuzzer' )
+1
View File
@@ -0,0 +1 @@
{"images":[{"uri":"%!QAAAQAAA5"}],"asset":{"version":""}}
Binary file not shown.
+1285
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+67
View File
@@ -0,0 +1,67 @@
# tests/v3/fuzzer/Makefile — Build libFuzzer harness for tinygltf v3
#
# Requires: clang++ with libFuzzer support
#
# Targets:
# make — build fuzzer with ASan + UBSan
# make run — run fuzzer with default settings
# make seed — generate seed corpus from test models
# make clean — remove binaries and corpus
CXX = clang++
CXXFLAGS = -g -O1 -std=c++17 -fno-rtti -fno-exceptions
SANITIZE = -fsanitize=fuzzer,address,undefined
INCLUDES = -I../../..
FUZZER = fuzz_gltf_v3
CORPUS = corpus
ARTIFACTS = artifacts
# Fuzzer runtime options
MAX_LEN ?= 65536
JOBS ?= $(shell nproc 2>/dev/null || echo 4)
MAX_TIME ?= 0
.PHONY: all run seed clean
all: $(FUZZER)
$(FUZZER): fuzz_gltf_v3.cc ../../../tiny_gltf_v3.h ../../../tinygltf_json.h
$(CXX) $(CXXFLAGS) $(SANITIZE) $(INCLUDES) -o $@ $<
run: $(FUZZER) | $(CORPUS) $(ARTIFACTS)
./$(FUZZER) $(CORPUS) \
-artifact_prefix=$(ARTIFACTS)/ \
-max_len=$(MAX_LEN) \
-jobs=$(JOBS) \
-workers=$(JOBS) \
$(if $(filter-out 0,$(MAX_TIME)),-max_total_time=$(MAX_TIME))
# Generate seed corpus from existing test models
seed: | $(CORPUS)
@echo "Seeding corpus from test models..."
@for f in ../../../models/Cube/Cube.gltf \
../../../models/Cube/Cube.glb; do \
if [ -f "$$f" ]; then \
cp "$$f" $(CORPUS)/; \
echo " Added: $$f"; \
fi; \
done
@# Add a minimal valid glTF JSON
@echo '{"asset":{"version":"2.0"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"name":"n"}]}' > $(CORPUS)/minimal.gltf
@# Add a minimal valid GLB (header + empty JSON chunk)
@printf 'glTF\x02\x00\x00\x00\x1c\x00\x00\x00\x04\x00\x00\x00JSON{} ' > $(CORPUS)/minimal.glb
@# Add edge cases
@echo '{}' > $(CORPUS)/empty_object.gltf
@echo '{"asset":{"version":"2.0"}}' > $(CORPUS)/asset_only.gltf
@echo "Corpus: $$(ls $(CORPUS) | wc -l) files"
$(CORPUS):
mkdir -p $(CORPUS)
$(ARTIFACTS):
mkdir -p $(ARTIFACTS)
clean:
rm -f $(FUZZER)
rm -rf $(CORPUS) $(ARTIFACTS)
+110
View File
@@ -0,0 +1,110 @@
/*
* fuzz_gltf_v3.cc — libFuzzer harness for tinygltf v3 parser.
*
* Fuzz targets:
* - Auto-detect (GLB or JSON) parse from arbitrary bytes
* - Exercises JSON parser, GLB header parsing, arena allocator,
* error stack, and all glTF entity parsing paths.
*
* Build (clang with libFuzzer):
* clang++ -g -O1 -fsanitize=fuzzer,address,undefined \
* -std=c++17 -fno-rtti -fno-exceptions \
* -I../../.. -o fuzz_gltf_v3 fuzz_gltf_v3.cc
*
* Run:
* ./fuzz_gltf_v3 corpus/ -max_len=65536
*
* Seed corpus: place valid .gltf and .glb files in corpus/
*/
#define TINYGLTF3_IMPLEMENTATION
#include "tiny_gltf_v3.h"
#include <cstdint>
#include <cstddef>
/* Memory budget to prevent OOM during fuzzing */
static const uint64_t FUZZ_MEMORY_BUDGET = 64ULL * 1024 * 1024; /* 64 MB */
static void fuzz_parse_auto(const uint8_t *data, size_t size) {
tg3_model model;
tg3_error_stack errors;
tg3_error_stack_init(&errors);
tg3_parse_options opts;
tg3_parse_options_init(&opts);
opts.memory.memory_budget = FUZZ_MEMORY_BUDGET;
tg3_parse_auto(&model, &errors, data, (uint64_t)size,
"", 0, &opts);
tg3_model_free(&model);
tg3_error_stack_free(&errors);
}
static void fuzz_parse_json(const uint8_t *data, size_t size) {
tg3_model model;
tg3_error_stack errors;
tg3_error_stack_init(&errors);
tg3_parse_options opts;
tg3_parse_options_init(&opts);
opts.memory.memory_budget = FUZZ_MEMORY_BUDGET;
tg3_parse(&model, &errors, data, (uint64_t)size,
"", 0, &opts);
tg3_model_free(&model);
tg3_error_stack_free(&errors);
}
static void fuzz_parse_glb(const uint8_t *data, size_t size) {
tg3_model model;
tg3_error_stack errors;
tg3_error_stack_init(&errors);
tg3_parse_options opts;
tg3_parse_options_init(&opts);
opts.memory.memory_budget = FUZZ_MEMORY_BUDGET;
tg3_parse_glb(&model, &errors, data, (uint64_t)size,
"", 0, &opts);
tg3_model_free(&model);
tg3_error_stack_free(&errors);
}
static void fuzz_parse_float32(const uint8_t *data, size_t size) {
tg3_model model;
tg3_error_stack errors;
tg3_error_stack_init(&errors);
tg3_parse_options opts;
tg3_parse_options_init(&opts);
opts.memory.memory_budget = FUZZ_MEMORY_BUDGET;
opts.parse_float32 = 1;
tg3_parse_auto(&model, &errors, data, (uint64_t)size,
"", 0, &opts);
tg3_model_free(&model);
tg3_error_stack_free(&errors);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size == 0) return 0;
/* Use first byte to select parse path, rest is the payload */
uint8_t selector = data[0] % 4;
const uint8_t *payload = data + 1;
size_t payload_size = size - 1;
switch (selector) {
case 0: fuzz_parse_auto(payload, payload_size); break;
case 1: fuzz_parse_json(payload, payload_size); break;
case 2: fuzz_parse_glb(payload, payload_size); break;
case 3: fuzz_parse_float32(payload, payload_size); break;
}
return 0;
}