From fe42b5e2996b8df235cd0a22f3fd9155b8d245cd Mon Sep 17 00:00:00 2001 From: theteatoast Date: Sat, 11 Apr 2026 02:52:54 +0530 Subject: [PATCH] Add OSS-Fuzz fuzz harness and seed corpus --- testing/fuzzing/fuzz_model_load.cc | 96 ++++++++++++++++++ .../fuzzing/seed_corpus/int32_max_dim.tflite | Bin 0 -> 1544 bytes testing/fuzzing/seed_corpus/malicious.tflite | Bin 0 -> 520 bytes .../seed_corpus/malicious_gather.tflite | Bin 0 -> 456 bytes .../seed_corpus/multidim_overflow.tflite | Bin 0 -> 520 bytes .../fuzzing/seed_corpus/near_overflow.tflite | Bin 0 -> 1544 bytes .../seed_corpus/negative_overflow.tflite | Bin 0 -> 1544 bytes .../seed_corpus/overflow_trigger.tflite | Bin 0 -> 520 bytes testing/fuzzing/seed_corpus/valid_rect.tflite | Bin 0 -> 552 bytes .../fuzzing/seed_corpus/valid_small.tflite | Bin 0 -> 536 bytes 10 files changed, 96 insertions(+) create mode 100644 testing/fuzzing/fuzz_model_load.cc create mode 100644 testing/fuzzing/seed_corpus/int32_max_dim.tflite create mode 100644 testing/fuzzing/seed_corpus/malicious.tflite create mode 100644 testing/fuzzing/seed_corpus/malicious_gather.tflite create mode 100644 testing/fuzzing/seed_corpus/multidim_overflow.tflite create mode 100644 testing/fuzzing/seed_corpus/near_overflow.tflite create mode 100644 testing/fuzzing/seed_corpus/negative_overflow.tflite create mode 100644 testing/fuzzing/seed_corpus/overflow_trigger.tflite create mode 100644 testing/fuzzing/seed_corpus/valid_rect.tflite create mode 100644 testing/fuzzing/seed_corpus/valid_small.tflite diff --git a/testing/fuzzing/fuzz_model_load.cc b/testing/fuzzing/fuzz_model_load.cc new file mode 100644 index 00000000000..89843f35102 --- /dev/null +++ b/testing/fuzzing/fuzz_model_load.cc @@ -0,0 +1,96 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); + +// fuzz_model_load.cc +// +// OSS-Fuzz harness for TensorFlow Lite Micro (tflite-micro). +// +// Pipeline exercised: +// GetModel(data) -> MicroInterpreter(model, resolver, arena, size) +// -> AllocateTensors() -> fill inputs -> Invoke() + + + +#include +#include +#include + +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/micro/micro_mutable_op_resolver.h" +#include "tensorflow/lite/schema/schema_generated.h" + + +constexpr int kArenaSize = 200000; +alignas(16) static uint8_t arena[kArenaSize]; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + + if (size < 8 || size > 4 * 1024 * 1024) { + return 0; + } + + + const tflite::Model *model = tflite::GetModel(data); + if (model == nullptr) { + return 0; + } + + // Basic null checks to avoid trivial nullptr crashes in the parser + if (model->subgraphs() == nullptr || model->subgraphs()->size() == 0) { + return 0; + } + if (model->buffers() == nullptr) { + return 0; + } + + + tflite::MicroMutableOpResolver<20> resolver; + // Integer overflow PoC ops + resolver.AddFullyConnected(); + resolver.AddDequantize(); + resolver.AddQuantize(); + resolver.AddReshape(); + // Gather OOB read PoC ops + resolver.AddGather(); + resolver.AddGatherNd(); + resolver.AddEmbeddingLookup(); + // Common TFLM ops for broader coverage + resolver.AddAdd(); + resolver.AddMul(); + resolver.AddSub(); + resolver.AddRelu(); + resolver.AddRelu6(); + resolver.AddSoftmax(); + resolver.AddLogistic(); + resolver.AddConv2D(); + resolver.AddDepthwiseConv2D(); + resolver.AddMaxPool2D(); + resolver.AddAveragePool2D(); + resolver.AddMean(); + + + tflite::MicroInterpreter interp(model, resolver, arena, kArenaSize); + + TfLiteStatus alloc_status = interp.AllocateTensors(); + if (alloc_status != kTfLiteOk) { + return 0; + } + + + for (size_t i = 0; i < interp.inputs_size(); ++i) { + TfLiteTensor *inp = interp.input(i); + if (inp == nullptr || inp->data.raw == nullptr || inp->bytes == 0) { + continue; + } + if (inp->bytes < (size_t)kArenaSize) { + for (size_t byte_idx = 0; byte_idx < inp->bytes; ++byte_idx) { + inp->data.raw[byte_idx] = data[byte_idx % size]; + } + } + } + + interp.Invoke(); + + return 0; +} \ No newline at end of file diff --git a/testing/fuzzing/seed_corpus/int32_max_dim.tflite b/testing/fuzzing/seed_corpus/int32_max_dim.tflite new file mode 100644 index 0000000000000000000000000000000000000000..1dd0c8d0309c95611be5bc9e2b7bb6bb717e9148 GIT binary patch literal 1544 zcmeH{K}rKb5JfB6Ceu2EfG)(<96&+>E(5tl7FoD)5p))bE)v`bX6Zp(cnA@X;2|Wd z++lpbdIoX_r{Pci{#DgoH8ho3T3=OFjXGwZCuY}388`+=HUMU)mfIONz>K!z~(?_%z@&MYK!rGlP{a{d!ElW7JO8T&S-L#uciHrx>e^b7=ZwG zXdl>&`{iTBZ#g*iiW<)kYTTmk@#!p9e6Qow%VC^q|G`(^9pB&z)tv=Uf7<_Ycd)K= z!|Gpj(I@T?uIJv3`U=j}pL(xrfTfl8+o_V^ofhpsXy3s9d;`tQWW2nJ%W6I}y13@d kcsRZpGL$rnmUra}B$%mryBVbn91!_oD zK~078O0tGapgV4X>W?x*9(VoX)Iack!dUasF1n-ZRlknn8}`S-1EWx z(qE%@1y_2X`tuH`PVcUDCw@q(wZ}y%&sOZrTA&ttRVNFH|v+pI_d3w N^YDm1A=j+jwtv`+CMEy? literal 0 HcmV?d00001 diff --git a/testing/fuzzing/seed_corpus/malicious_gather.tflite b/testing/fuzzing/seed_corpus/malicious_gather.tflite new file mode 100644 index 0000000000000000000000000000000000000000..5ade40ef61521cb563b603eb1c5be8ce6a352d76 GIT binary patch literal 456 zcmYL_F;2rk5Jkt1L6&00E|5q;;lf1$(rmEYbN+T#1R8iHEXzdp)G<^-WsTw`MAHb&>X1 zerSP3vY8;Km0>TOJF~gGL>1JbM?4pEL7z$lVq0!@GET!E?06ovuxL#OEqZEQhT6CT zefbwyoO8{_EaM%o<^L%5EKB}fMDC99|12xT1`WS(dAgov#Yb}?&PCle`?l%*m%2Vw vN3%1y@(7_y6-}W@pxgrSsFa?YL+54X&{Ya101-2+U5cv@|AKCI{6K4#X4XLOQ@mq#uz_oX^)CkaGtUS2 zOMi{t6hE?yWxbi}PW+zccK>aWS-I>>YtCdenT}XW@$-GNgxr5wuU^-yq~9Kz M$0u~3T(flB_SZ}%A^-pY literal 0 HcmV?d00001 diff --git a/testing/fuzzing/seed_corpus/near_overflow.tflite b/testing/fuzzing/seed_corpus/near_overflow.tflite new file mode 100644 index 0000000000000000000000000000000000000000..f549050cc57c75582f8341b2ba50f5f0a5075781 GIT binary patch literal 1544 zcmeH{F-`(e5QYbR;y&CE5-g03djLZqu{7Zl6c#oVM7IzvAT}119>jt}7~>H*1hMiC z>-W#wO}K;mlArnKpPBb&$YwH2=c}r!amVcQ#OxX=1IGZ#2EeRmxt(DHEa{l2_&G4^ z+XZYuRz^-A<&C=vYz}nC9Z>#JZ87dQ^|Gn{)a!9$!H;^;9Zjw3b>z?JTYcVxF$mxX zZHvu#UolSnR)AYC>2Y|_;|BGYnC{}lk2+7Y9OkL_9kKfD_zqX9-YkITlfUQfU|r{i z)ql}Nzx8->hwx+OjKANVP^~~P)%}${T&<9X90%nI++7U9KB_0vwKL%z) zJ3$)}RS+|Td8Sr{EP-lV0mbiSiEz8kmrVHwo{t$T9_mFk+Fa%9$iAd+^?40uAb=mZ zH)O&6@^Rv)98{gq<9MgXE$lBo)#Ak09H&`!>CB$%mryBVbn91!_oD zK~078O0tGapgV4X>W?x*9(VoX)Iack!dUasF1n-ZRlknn8}`S-1EWx z(qE%@1y_2X`tuH`PVcUDCw@q(wZ}y%&sOZrTA&ttRVNFH|v+pI_d3w N^YDm1A=j+jwtv`+CMEy? literal 0 HcmV?d00001 diff --git a/testing/fuzzing/seed_corpus/valid_rect.tflite b/testing/fuzzing/seed_corpus/valid_rect.tflite new file mode 100644 index 0000000000000000000000000000000000000000..f5b4404467126648f2767e6b1b26bb5c24c83f62 GIT binary patch literal 552 zcmaiwJx&5q6ooJP#CbBAkYHh`rlc?g5=s*{VPRoIL39ei0z%6|T!5>vav2sDgqj@; z-??ulq4OqZ&i#MqPG-rz>$;wF%znW=sSI2KLhA#w8_TT+2fUPrqUyK6tgt)0K3y3- z1({EZC7c88cn0dfXc+RiofoJ1Yo8~KB_CM7l{GHc> z=X1YCcLn!!pKfn7;3Z4(Zl<^KJ8ejZ_6h&_+B+RjZ^wvK-|C@SL$2p}yLs7elK;A_ N9-r{L)T*_o?FbQ|CPn}N literal 0 HcmV?d00001