Skip to content

Commit 6aac58f

Browse files
committed
Add new project: raylib
raylib is a C game development library (~23K stars) with built-in model file parsers for OBJ, IQM, GLTF, VOX, and M3D formats. All parsers process untrusted input when users load model files in games, modding tools, and asset pipelines. This adds a libFuzzer harness targeting raylib's model loading dispatch (LoadModel → LoadOBJ/LoadIQM/LoadGLTF/LoadVOX/LoadM3D) with GPU/windowing stubs for headless fuzzing. Sanitizers: ASan + UBSan. Engines: libFuzzer, AFL, honggfuzz.
1 parent 675ddfb commit 6aac58f

File tree

6 files changed

+418
-0
lines changed

6 files changed

+418
-0
lines changed

projects/raylib/Dockerfile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
################################################################################
16+
17+
FROM gcr.io/oss-fuzz-base/base-builder
18+
19+
RUN apt-get update && apt-get install -y --no-install-recommends \
20+
cmake make && \
21+
rm -rf /var/lib/apt/lists/*
22+
23+
RUN git clone --depth 1 https://github.com/raysan5/raylib.git $SRC/raylib
24+
25+
COPY build.sh $SRC/
26+
COPY raylib_fuzz_model.c $SRC/
27+
COPY raylib_stubs.c $SRC/
28+
COPY raylib_model.dict $SRC/

projects/raylib/build.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash -eu
2+
# Copyright 2026 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
################################################################################
17+
18+
cd $SRC/raylib
19+
20+
$CC $CFLAGS -I./src -I./src/external \
21+
-DSUPPORT_TRACELOG=0 -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33 \
22+
-c ./src/rmodels.c -o rmodels.o
23+
24+
$CC $CFLAGS -I./src -I./src/external \
25+
-DSUPPORT_TRACELOG=0 -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33 \
26+
-c $SRC/raylib_stubs.c -o raylib_stubs.o
27+
28+
$CC $CFLAGS -I./src \
29+
-DRAYMATH_IMPLEMENTATION \
30+
-c -x c /dev/null -include ./src/raymath.h -o raymath_impl.o 2>/dev/null || \
31+
echo 'extern int raymath_dummy;' | $CC $CFLAGS -c -x c - -o raymath_impl.o
32+
33+
$CC $CFLAGS -I./src -I./src/external \
34+
-DSUPPORT_TRACELOG=0 -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33 \
35+
$SRC/raylib_fuzz_model.c rmodels.o raylib_stubs.o raymath_impl.o \
36+
$LIB_FUZZING_ENGINE -lm -lpthread \
37+
-o $OUT/raylib_fuzz_model
38+
39+
cp $SRC/raylib_model.dict $OUT/raylib_fuzz_model.dict
40+
41+
mkdir -p /tmp/raylib_seeds
42+
printf '\x00# OBJ\nv 0.0 0.0 0.0\nv 1.0 0.0 0.0\nv 0.0 1.0 0.0\nf 1 2 3\n' > /tmp/raylib_seeds/seed_obj
43+
printf '\x01INTERQUAKEMODEL\x00\x02\x00\x00\x00' > /tmp/raylib_seeds/seed_iqm
44+
dd if=/dev/zero bs=1 count=100 >> /tmp/raylib_seeds/seed_iqm 2>/dev/null
45+
printf '\x02{"asset":{"version":"2.0"}}' > /tmp/raylib_seeds/seed_gltf
46+
printf '\x04VOX \x96\x00\x00\x00' > /tmp/raylib_seeds/seed_vox
47+
dd if=/dev/zero bs=1 count=50 >> /tmp/raylib_seeds/seed_vox 2>/dev/null
48+
printf '\x053DMO' > /tmp/raylib_seeds/seed_m3d
49+
dd if=/dev/zero bs=1 count=50 >> /tmp/raylib_seeds/seed_m3d 2>/dev/null
50+
51+
cd /tmp/raylib_seeds && zip -q -j $OUT/raylib_fuzz_model_seed_corpus.zip *

projects/raylib/project.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
homepage: "https://github.com/raysan5/raylib"
2+
language: c
3+
primary_contact: "shravankumarsheri39@gmail.com"
4+
auto_ccs:
5+
- "shravankumarsheri39@gmail.com"
6+
main_repo: "https://github.com/raysan5/raylib.git"
7+
file_github_issue: true
8+
sanitizers:
9+
- address
10+
- undefined
11+
architectures:
12+
- x86_64
13+
fuzzing_engines:
14+
- libfuzzer
15+
- afl
16+
- honggfuzz
17+
vendor_ccs: []
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
////////////////////////////////////////////////////////////////////////////////
16+
// raylib model loader fuzzer harness
17+
// Targets: OBJ, IQM, GLTF, VOX, M3D parsers
18+
19+
#include <stdint.h>
20+
#include <stddef.h>
21+
#include <stdio.h>
22+
#include <stdlib.h>
23+
#include <string.h>
24+
#include <unistd.h>
25+
26+
#include "raylib.h"
27+
28+
static const char *extensions[] = {
29+
".obj", ".iqm", ".gltf", ".glb", ".vox", ".m3d",
30+
};
31+
#define NUM_EXTENSIONS 6
32+
#define MAX_INPUT_SIZE (256 * 1024)
33+
34+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
35+
if (size < 2 || size > MAX_INPUT_SIZE) return 0;
36+
37+
int ext_idx = data[0] % NUM_EXTENSIONS;
38+
const uint8_t *payload = data + 1;
39+
size_t payload_size = size - 1;
40+
41+
char tmppath[256];
42+
snprintf(tmppath, sizeof(tmppath), "/dev/shm/fuzz_raylib_%d%s",
43+
getpid(), extensions[ext_idx]);
44+
45+
FILE *f = fopen(tmppath, "wb");
46+
if (!f) return 0;
47+
fwrite(payload, 1, payload_size, f);
48+
fclose(f);
49+
50+
Model model = LoadModel(tmppath);
51+
52+
// Manual cleanup to avoid GPU stub issues in UnloadModel
53+
if (model.meshes != NULL) {
54+
for (int i = 0; i < model.meshCount; i++) {
55+
RL_FREE(model.meshes[i].vertices);
56+
RL_FREE(model.meshes[i].texcoords);
57+
RL_FREE(model.meshes[i].texcoords2);
58+
RL_FREE(model.meshes[i].normals);
59+
RL_FREE(model.meshes[i].tangents);
60+
RL_FREE(model.meshes[i].colors);
61+
RL_FREE(model.meshes[i].indices);
62+
RL_FREE(model.meshes[i].animVertices);
63+
RL_FREE(model.meshes[i].animNormals);
64+
RL_FREE(model.meshes[i].boneWeights);
65+
RL_FREE(model.meshes[i].boneIndices);
66+
RL_FREE(model.meshes[i].vboId);
67+
}
68+
RL_FREE(model.meshes);
69+
}
70+
RL_FREE(model.materials);
71+
RL_FREE(model.meshMaterial);
72+
RL_FREE(model.skeleton.bones);
73+
RL_FREE(model.boneMatrices);
74+
75+
unlink(tmppath);
76+
return 0;
77+
}

projects/raylib/raylib_model.dict

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# OBJ keywords
2+
"v "
3+
"vt "
4+
"vn "
5+
"f "
6+
"o "
7+
"g "
8+
"s "
9+
"usemtl "
10+
"mtllib "
11+
"# "
12+
13+
# IQM magic and keywords
14+
"INTERQUAKEMODEL\x00"
15+
"\x02\x00\x00\x00"
16+
17+
# GLTF/GLB
18+
"glTF"
19+
"{\"asset\""
20+
"\"version\""
21+
"\"2.0\""
22+
"\"meshes\""
23+
"\"accessors\""
24+
"\"bufferViews\""
25+
"\"buffers\""
26+
"\"nodes\""
27+
"\"scenes\""
28+
"\"materials\""
29+
"\"primitives\""
30+
"\"attributes\""
31+
"\"POSITION\""
32+
"\"NORMAL\""
33+
"\"TEXCOORD_0\""
34+
"\"indices\""
35+
"\"mode\""
36+
"\"componentType\""
37+
"\"count\""
38+
"\"type\""
39+
"\"VEC3\""
40+
"\"VEC2\""
41+
"\"SCALAR\""
42+
"\"byteOffset\""
43+
"\"byteLength\""
44+
"\"uri\""
45+
"\"bin\""
46+
47+
# VOX magic
48+
"VOX "
49+
"MAIN"
50+
"SIZE"
51+
"XYZI"
52+
"RGBA"
53+
"\x96\x00\x00\x00"
54+
55+
# M3D magic
56+
"3DMO"
57+
"\x84\xAC\xD1\x73"

0 commit comments

Comments
 (0)