From 22fdb8c4e82e9001080aaed0ff208bd52cc808b3 Mon Sep 17 00:00:00 2001 From: Topogamer0 Date: Mon, 26 Oct 2026 22:03:41 +0100 Subject: [PATCH] Fuzz: add libFuzzer fuzzers for OSS-Fuzz Add five fuzzers in fuzz/, built when the new BUILD_FUZZERS CMake option is ON (default OFF, so the normal build is unchanged): - parser_fuzzer: decodes a sequence of items and visits every one of them, nested ones included, extracting every value and cross-checking the different APIs (copy vs dup vs chunked strings, checked vs unchecked integers, cbor_value_advance vs item-by-item traversal). Optionally uses the reader API, including cbor_value_reparse() with incrementally available data. - validate_fuzzer: cbor_value_validate() with any combination of flags. - tojson_fuzzer: cbor_value_to_json_advance() with any flags. - pretty_fuzzer: cbor_value_to_pretty_advance_flags() and cbor_value_to_pretty_stream() with any flags. - encoder_fuzzer: interprets the input as a sequence of encoder commands, runs it with a fixed-size buffer (and again with the size from cbor_encoder_get_extra_bytes_needed()) and with a writer function, then parses the result back, validates it and compares it to what was encoded. The fuzzers must be built without NDEBUG, as the assertions check that the API is used correctly. The seed corpus is the CBOR data from the unit tests, minimized for coverage; cbor.dict lists the initial bytes of the CBOR types. The fuzzers were written with the help of Claude Code and reviewed and tested by me. Signed-off-by: Topogamer0 --- CMakeLists.txt | 4 + fuzz/CMakeLists.txt | 52 ++ fuzz/README | 40 + fuzz/cbor.dict | 105 +++ .../014f895dd135e86b9c26361a455ce9bf15a09fda | Bin 0 -> 32 bytes .../05e70084b7f8d73c500867cfbc579ea65ca3af32 | Bin 0 -> 7 bytes .../086c1bebeb1c5b2c20aefcb15ff8959c4402f65a | Bin 0 -> 12 bytes .../09d360a8595c2bb49f808c2e0841586737fed1f7 | Bin 0 -> 6 bytes .../0a033e3d52c5a619fb6c65e790a88e07c68d704d | Bin 0 -> 19 bytes .../0b7297f312717b3024fc4062079985bcf192589d | Bin 0 -> 9 bytes .../0c8c3f1dc468af54b996c44219cf4816a0037ca6 | Bin 0 -> 6 bytes .../0df3f4d23dcecbb7926dee75666404b1e9b67c40 | Bin 0 -> 9 bytes .../10cd401ccee82e25d326c9ce0dd6f7419c837a80 | Bin 0 -> 5 bytes .../13887ac5dc6c08d719daaa094c143f2955e553ef | Bin 0 -> 6 bytes .../1409c17079b2428205273f09eedc8df201e40be8 | Bin 0 -> 7 bytes .../15b9bcdcdcaaddd89bec8ed27e3910631837c564 | Bin 0 -> 6 bytes .../15cfc192a73e1718c34cae0ec98ff9f66f4997d8 | Bin 0 -> 16 bytes .../199e138c7b38a2936099f37839bd1422fc94bc16 | Bin 0 -> 6 bytes .../1adb291927afd05380e83f87133422350eab2557 | Bin 0 -> 7 bytes .../1bc07015c76422ba9310425720dee495754458d6 | Bin 0 -> 7 bytes .../1bdde59cf453795380dc12a70053a8e5ea05e3d8 | Bin 0 -> 32 bytes .../1c3a23b9e6943d5b9be200d1999df9917163eba2 | Bin 0 -> 7 bytes .../2225d2f8215c9e415ac6ce0d41855413fa460307 | Bin 0 -> 5 bytes .../23c8f61758d49990b5633c3da32e6ad02bbff30c | Bin 0 -> 13 bytes .../24ab22a223f470d3c112238c1ee7384614cdf8e0 | Bin 0 -> 9 bytes .../25a928530b1982973183c9d1b64cb500d3b54c3c | Bin 0 -> 11 bytes .../2934ab98a050eb4187581b73d028d20a2d5beeca | Bin 0 -> 6 bytes .../2b12413703657e68436d0a6196461b9fc1333b77 | Bin 0 -> 9 bytes .../2bb8fa769be54095af1baefcc4f40d8563d25630 | Bin 0 -> 9 bytes .../31af79055f44c1226f87c02ea97bb442d20b5d7f | Bin 0 -> 7 bytes .../3371ce6be3d727bc05559e06c5e3014e43972297 | Bin 0 -> 12 bytes .../3388e311ce4feda955c6d268047166485e8bc1ef | Bin 0 -> 6 bytes .../338e72b519807fd9041fa921ac4dc42f354e064d | Bin 0 -> 10 bytes .../33cdae5f3d9e02f549f8d4e69bceb0850190c78d | Bin 0 -> 29 bytes .../33db23a38ab67ce204fd304e95d8908fa72ae194 | Bin 0 -> 6 bytes .../34e11cb5310343ced27d0d06b3aa716c4927e701 | Bin 0 -> 10 bytes .../3526e9257647e436cdbefd57476a0ee7f8d04079 | Bin 0 -> 9 bytes .../3539e2d8ddc8acc73d33771dd038ef8279db8a61 | Bin 0 -> 11 bytes .../38a5f141a69fc4a7d743f558195c0e11cf01cb09 | Bin 0 -> 5 bytes .../3a9387b8cb1f1c49a0225c1d5b017df766622c4c | Bin 0 -> 15 bytes .../3a9eccb024e670ba60dd68e6dbc6941d9856009d | Bin 0 -> 9 bytes .../3b5aa3f4c1a38f16fb96f03d86f73142490a3977 | Bin 0 -> 8 bytes .../3ddf0e90744d3dd73cf395f85fa8864233e58704 | Bin 0 -> 8 bytes .../3e2b2f0ab1581461dfc9e0b2b6d33244df8b9507 | Bin 0 -> 7 bytes .../3e5432a0f6ec0b3b6577462b5574f8bbdf964020 | Bin 0 -> 8 bytes .../3fcbfab37368a03f327a90b9314800eb392f9aa9 | Bin 0 -> 25 bytes .../419141f38e7bd8efcf3bc5c55742692a10c050f1 | Bin 0 -> 12 bytes .../41b04a983188a907a110c63971b21151c9843843 | Bin 0 -> 7 bytes .../469deca0443da8487a9119ab1900f269ab97913b | Bin 0 -> 6 bytes .../47d6dc79f407358af11ff1271d0c4a2b4f366e2f | Bin 0 -> 7 bytes .../4935117d68863051ef3eee686e3fa335bc85a33b | Bin 0 -> 12 bytes .../4c15423f492dcade8bc1f6a4d4df64f20e34bb67 | Bin 0 -> 7 bytes .../4cc6c9971bf85188da00d466f88f8407b6761293 | Bin 0 -> 25 bytes .../4f4235cc7ef3ba2972e976f9170a4089f4be43b4 | Bin 0 -> 13 bytes .../5206b211b425fa5601783562fc254972a5527757 | Bin 0 -> 6 bytes .../52a670d56c5a6d7af94c402ca654988587e576d5 | Bin 0 -> 43 bytes .../531250e07aa93ce051b3bd354107f4fe8cdb435a | Bin 0 -> 10 bytes .../5371a4f527a693ac664c0fd647a5eabc036c5d17 | Bin 0 -> 13 bytes .../5521945da7469e0136707f2d1445a170ef6c3f84 | Bin 0 -> 28 bytes .../556e1fa17f8b24bb601377ac747ea4479274d59a | Bin 0 -> 8 bytes .../56e836645bd178d8f7586ba5277ec58d1359e16a | Bin 0 -> 10 bytes .../56f78df0ffeb23e148a0b12acb3ed2b43feed6d9 | Bin 0 -> 14 bytes .../57996c03c2e504cb16d7dbcb30f31d3ab7356913 | Bin 0 -> 9 bytes .../5b184fd25a784954bbe08ddae81bb85193c0edcf | Bin 0 -> 11 bytes .../5c69c00bb03a69f66a68cefe51a7ab9c5729266b | Bin 0 -> 11 bytes .../5f9ac4584d79796138ed1b02eb51da20b269d56b | Bin 0 -> 36 bytes .../62d74378c462475adc37477b8512f53cb2469943 | Bin 0 -> 6 bytes .../63825b8d35cb53f9aa0f8adea417e79e39e9e2a0 | Bin 0 -> 6 bytes .../64f13a6846284c580a9038e50dd501e0b9a58408 | Bin 0 -> 10 bytes .../65da5e58845e3d63e86765eb54108abb64f8375a | Bin 0 -> 6 bytes .../693e002a34afd6bb8dab5772f3bc3d1d3cec210d | Bin 0 -> 14 bytes .../6b86233c7df6e2f956777e0483d5854d8a460c39 | Bin 0 -> 15 bytes .../6c3f6c108f8cf3e1ddbffb4159038e39b0d0b057 | Bin 0 -> 7 bytes .../6ed55b9c0d90d80924c48bf1b11b8103f741926e | Bin 0 -> 6 bytes .../6f88ebe387c78c8b302633de4cc1fdffe5f660ca | Bin 0 -> 6 bytes .../7161b6ffe9a2efc1c8598dbd496cfcf7034d0043 | Bin 0 -> 26 bytes .../722adabc5640a783b2f8f2500f28764b4ac6aaf3 | Bin 0 -> 17 bytes .../72549fa4dfc341f9b5aa0369021210d727a25b7d | Bin 0 -> 12 bytes .../73ebe48acb4c94ee354584cc54cce01e62868bf7 | Bin 0 -> 13 bytes .../744a71d6a17275896f51f084fd56279502086687 | Bin 0 -> 48 bytes .../749798e4ffcb312af64c726b60031643c1a7ae4f | Bin 0 -> 11 bytes .../75ec53f355a6c3a90cf2dcc24ddbb2446081b9cb | Bin 0 -> 12 bytes .../75ed39927daeab8292dc6f6c695e054eefa7f634 | Bin 0 -> 39 bytes .../784da0594a769a4cb3e52cb60b9a2cf669b10116 | Bin 0 -> 16 bytes .../785ece10aa6b6dfda662f87abef617f3398ac9a6 | Bin 0 -> 10 bytes .../7a327da3074102e0539f06bcad19c1e8ce28844a | Bin 0 -> 8 bytes .../7ae651f8139ddaaa91220f141f96b2ab0f4f1b1d | Bin 0 -> 48 bytes .../7b2ec7e552b0a19d42c7c0c4b7d3e9f0687eba9e | Bin 0 -> 9 bytes .../7ba72368458f84a104187d7a7ae98ef9451aa754 | Bin 0 -> 5 bytes .../7cec76a63eebb15a620b9f1bb58bcff223629c0d | Bin 0 -> 7 bytes .../7f3dc1b701ab60200ac463fc4b57aa4fc498522e | Bin 0 -> 6 bytes .../7f895ef6eed5ff4669394fd3b7b864dbde83b36f | Bin 0 -> 8 bytes .../83623f2b6453da9f0fe497745853c8df03a5b942 | Bin 0 -> 31 bytes .../839c5d2fe334f6bee779a01a6cad244e0bc6ee3a | Bin 0 -> 6 bytes .../85c18dd8dc33ea9703ab3b67bd6d976188932ad1 | Bin 0 -> 7 bytes .../87b5e15e41d61dcce8befa6be032bf32bc862599 | Bin 0 -> 17 bytes .../87e7ac9dbb6aace3fca5e87df7347b4a9b606530 | Bin 0 -> 6 bytes .../88f93b9e3bc228dad823fe1fcb9d67776f63d045 | Bin 0 -> 5 bytes .../8a2de019e26cd22fe9f797b48c6edbac3b509f1c | Bin 0 -> 9 bytes .../8df289206a301da6f097e7108044b817834448fd | Bin 0 -> 13 bytes .../8f1eda3de0bf21c6e4ec77af5fdc3a68abaaf6b5 | Bin 0 -> 6 bytes .../8faa8c23d29ae9628519eb50d49106580bb49a9e | Bin 0 -> 6 bytes .../913fddf15ed755486038346a61da94380885f871 | Bin 0 -> 13 bytes .../929510601da41d3b093e08eb172c360b078beb37 | Bin 0 -> 8 bytes .../95ca61e0b847c5ca2014598932a87d5f4fd224c3 | Bin 0 -> 9 bytes .../95dc062c15738f5547ee1bd184b2bdc9e6863179 | Bin 0 -> 39 bytes .../95ece661a83f44d6ad347fe956156935de828310 | Bin 0 -> 5 bytes .../962f0f994e9f2f45028be48317a9b099b479c88b | Bin 0 -> 25 bytes .../9690f81d995c899149953cfda66c494bfbf9f932 | Bin 0 -> 21 bytes .../988ac4cd44d339f917d20329f0b83cb911098134 | Bin 0 -> 6 bytes .../9a08160f112708ae57fe800e1a513936b5ff6fed | Bin 0 -> 10 bytes .../9b2446528d0cb9316575d3329fca50383a568681 | Bin 0 -> 7 bytes .../9b91e3ff93d9576a92fe1611f083f754c2e0c12c | Bin 0 -> 13 bytes .../9c3b4a7a3190481d1962e8aaa7ee080ed756e371 | Bin 0 -> 6 bytes .../9e696677edd5d0e273e23553b4ee5362f1876f35 | Bin 0 -> 17 bytes .../9e891040b46c530baab056ec2e114eaacf34945f | Bin 0 -> 23 bytes .../9f9fbb4007d7c8f37d131a919b540889d1d9e4bc | Bin 0 -> 12 bytes .../a02172af424a66f6fc9a278213adfa944f7608fd | Bin 0 -> 7 bytes .../a03f1dcf20bbdd19ebefe4f80cf38d799c8c00c4 | Bin 0 -> 11 bytes .../a0a174d3d10f29c30356e231947b9051c4e6be54 | Bin 0 -> 8 bytes .../a0d5afca37acf3d7eea972dd2977f3ffe4a8f37d | Bin 0 -> 8 bytes .../a1ba5f16e0e092d24f7857752935b290e0124e72 | Bin 0 -> 16 bytes .../a3e78b1df456fd877b9f6179f135a5d98378b29c | Bin 0 -> 6 bytes .../a7473834a9451bf3bb31ee5278bba4bdd43a6f1f | Bin 0 -> 13 bytes .../a7cdd52296420455fc828ddd761ea103dbb456d0 | Bin 0 -> 8 bytes .../a7dacaf428193dae8af833750cef9a6d00b5c773 | Bin 0 -> 6 bytes .../a9b7509a44e1cddcd3e79115d15da0fb6084459a | Bin 0 -> 8 bytes .../aac03222d9b7a4fb9933e8f65538338cb28d6389 | Bin 0 -> 13 bytes .../ab6ad7b89748a1fe481186f091f9e391c426726a | Bin 0 -> 13 bytes .../b04cfc32b841d9438740b4aab517588d3cfdbdb5 | Bin 0 -> 8 bytes .../b0d538ba10aa6aca3af422156c25e592df549bfa | Bin 0 -> 6 bytes .../b0f3fda2e1bf328f1d6f3f1497aa7fa4c02cbf65 | Bin 0 -> 9 bytes .../b31db2a9303539638df51abecaea9edc4d0aa660 | Bin 0 -> 10 bytes .../b3e2615d6c47bd80f5e5a4b0ed3f208d5628cd20 | Bin 0 -> 25 bytes .../b44d71cf10b459b618a5b31186cf92b5cc302bc7 | Bin 0 -> 10 bytes .../b5220686b2d4f078319318dcafdcaff665fe6c8d | Bin 0 -> 5 bytes .../b6ddeebc1d724c77817a0b9ab5d390e26303e03e | Bin 0 -> 9 bytes .../b7336217e23ff6cddc65cb7c798fc71e207bac6d | Bin 0 -> 6 bytes .../b78d7aac72fdcec7bb5fede4cdd570287d37ad54 | Bin 0 -> 7 bytes .../bb9bf63afed6ba7543f9ff957f03baf383bcd00b | Bin 0 -> 11 bytes .../bef08279879afd4e08e0521f0b646877d7037b69 | Bin 0 -> 30 bytes .../c0df355f326bb9914e67bf7da788853c914fc704 | Bin 0 -> 16 bytes .../c3f035a36c11df93158ed7111b880c3a372ea835 | Bin 0 -> 7 bytes .../c3fb0103c6da6d6158209bd99aeca5a359a15639 | Bin 0 -> 8 bytes .../c41e90f8c259305e7eef5818f762b7f8363fdb2f | Bin 0 -> 7 bytes .../c41efbb0f5b4a095bd3bb1638a8cbfe89ab761d7 | Bin 0 -> 9 bytes .../c7ad6adc133f798b5cfff03a27ab95c394c048c0 | Bin 0 -> 5 bytes .../c96bb8bdd516bb5cd2f51ea887b02c95974ce850 | Bin 0 -> 11 bytes .../ca3971ff6a78ec291e71d633948c5881ee928d57 | Bin 0 -> 9 bytes .../cae31911e8672e5d7ca0444eb70aeb86aa0f89c9 | Bin 0 -> 6 bytes .../cc30e664354997c9b2eeacc8cf80ebe9d6981232 | Bin 0 -> 6 bytes .../ccbc73bfebcc697019281a88d69ed411abd022b3 | Bin 0 -> 7 bytes .../ccc9b5c481c7005a2b18c6f7b3895d57055b57c3 | Bin 0 -> 9 bytes .../ce778ab2b71c7520a4bf6a53c71ae8788b92abd7 | Bin 0 -> 9 bytes .../cece690ab3ae1d247b714f0d31bf47b315d5232d | Bin 0 -> 8 bytes .../d0c1f6a6ee9e21381e14d656da926258b063b41d | Bin 0 -> 27 bytes .../d2896fed2190b5bd98329d9758c26e5bc441ae5b | Bin 0 -> 6 bytes .../d44ae1090f46442bf6f82571122388c07ff2df5b | Bin 0 -> 15 bytes .../d643dddfa978b15326ac185fd8592a4064e213a4 | Bin 0 -> 6 bytes .../d8cd66165e33ac8171904dec514c4f50ab610cdb | Bin 0 -> 6 bytes .../d9f33a1e75a97cc33db614bc02d71d8fd4176ee4 | Bin 0 -> 7 bytes .../dadbd79924eef32b6199431701f3c8e7bad9fdcc | Bin 0 -> 7 bytes .../de19e810b9e2ebb6b12dd37b5e7d1076f34af5dd | Bin 0 -> 7 bytes .../de61430a06e786fa828a1841997ca746f314a50f | Bin 0 -> 20 bytes .../df3bc063c169d37389a06837ed46208f1fe1c25b | Bin 0 -> 6 bytes .../e0aceb3ef023d2f1af7eb7c8926a1b1df5cdbe89 | Bin 0 -> 7 bytes .../e14e7128b5b6eb4fd639e7510a9e58b4fc91fbec | Bin 0 -> 27 bytes .../e1a4624b772e1c6f5bc3f85ae05d2853dbaeeceb | Bin 0 -> 7 bytes .../e1b5f7e47927e4843e9b029365eb6a5a6e8530d2 | Bin 0 -> 8 bytes .../e64ba7edd4532eff9b608d6877c63eb35d3bb65e | Bin 0 -> 5 bytes .../e7542ae2ec4ae9324af87522693fa2a84e0258ce | Bin 0 -> 8 bytes .../e7bfe09199cdf08f4e43dd7faf1526043aefeb62 | Bin 0 -> 7 bytes .../e887d9a2218498334f1f5ca31610312bee121842 | Bin 0 -> 7 bytes .../e8e62b69bc04cb5ed30fb7fad6e2a77c320f88f5 | Bin 0 -> 8 bytes .../ebca472922552feb96b5a1fb246827e155ef2549 | Bin 0 -> 7 bytes .../ec30f45e3fa2f22524a1edf302dd5cf739e2a2e6 | Bin 0 -> 8 bytes .../ecbdd50b499c5ee8d76340846bbc3e9ffc20bd4f | Bin 0 -> 9 bytes .../ed244dab55c0d6fbb36ab9d4bc33c22f8d7653b0 | Bin 0 -> 5 bytes .../ee1e299cce1b26876ce104f944c81abd59233afb | Bin 0 -> 6 bytes .../efbf741518ed3a5b72cbff940acf2b34e816ecfb | Bin 0 -> 9 bytes .../f08abb06077a2e1699becdfbf16e92d3a54f2fa1 | Bin 0 -> 6 bytes .../f2f074dfe49dbe033fe324236aead5176b8938b5 | Bin 0 -> 7 bytes .../f404023e17bbf5179c1d2a65d8e5656f60123e17 | Bin 0 -> 9 bytes .../f5fb06e95d6695b370477edefb4c300298cbe2cf | Bin 0 -> 14 bytes .../f602046b30549b3f62dd5ab123d28094521aa513 | Bin 0 -> 10 bytes .../f84127d4aefd8cf967c8d1ad7efc9a7ef0a83fd1 | Bin 0 -> 6 bytes .../f87df90d7bc4c3081af67a387f13a2f5e5e7b663 | Bin 0 -> 18 bytes .../f961cfb05ce44cfbb80b49108f1c24f203e53008 | Bin 0 -> 26 bytes .../f96d3c8ec87eb79a2d5a32e766f2fa364a1787d8 | Bin 0 -> 7 bytes .../fa056d3eebf1859a8b702d2520d3f879913ce8d7 | Bin 0 -> 5 bytes .../fa253cc79703f60938775baede93c2cab056d6da | Bin 0 -> 9 bytes .../fa7622e5400b857832a96fd860653b10c9ba4f52 | Bin 0 -> 8 bytes .../fb71d501937402a04cfeca84078922fe59ee75f3 | Bin 0 -> 9 bytes .../fb888d425a2cef4158ef3bf0b456dfa9acec78a0 | Bin 0 -> 6 bytes fuzz/encoder_fuzzer.c | 728 ++++++++++++++++++ fuzz/parser_fuzzer.c | 525 +++++++++++++ fuzz/pretty_fuzzer.c | 121 +++ fuzz/tojson_fuzzer.c | 123 +++ fuzz/validate_fuzzer.c | 87 +++ 199 files changed, 1785 insertions(+) create mode 100644 fuzz/CMakeLists.txt create mode 100644 fuzz/README create mode 100644 fuzz/cbor.dict create mode 100644 fuzz/corpus/014f895dd135e86b9c26361a455ce9bf15a09fda create mode 100644 fuzz/corpus/05e70084b7f8d73c500867cfbc579ea65ca3af32 create mode 100644 fuzz/corpus/086c1bebeb1c5b2c20aefcb15ff8959c4402f65a create mode 100644 fuzz/corpus/09d360a8595c2bb49f808c2e0841586737fed1f7 create mode 100644 fuzz/corpus/0a033e3d52c5a619fb6c65e790a88e07c68d704d create mode 100644 fuzz/corpus/0b7297f312717b3024fc4062079985bcf192589d create mode 100644 fuzz/corpus/0c8c3f1dc468af54b996c44219cf4816a0037ca6 create mode 100644 fuzz/corpus/0df3f4d23dcecbb7926dee75666404b1e9b67c40 create mode 100644 fuzz/corpus/10cd401ccee82e25d326c9ce0dd6f7419c837a80 create mode 100644 fuzz/corpus/13887ac5dc6c08d719daaa094c143f2955e553ef create mode 100644 fuzz/corpus/1409c17079b2428205273f09eedc8df201e40be8 create mode 100644 fuzz/corpus/15b9bcdcdcaaddd89bec8ed27e3910631837c564 create mode 100644 fuzz/corpus/15cfc192a73e1718c34cae0ec98ff9f66f4997d8 create mode 100644 fuzz/corpus/199e138c7b38a2936099f37839bd1422fc94bc16 create mode 100644 fuzz/corpus/1adb291927afd05380e83f87133422350eab2557 create mode 100644 fuzz/corpus/1bc07015c76422ba9310425720dee495754458d6 create mode 100644 fuzz/corpus/1bdde59cf453795380dc12a70053a8e5ea05e3d8 create mode 100644 fuzz/corpus/1c3a23b9e6943d5b9be200d1999df9917163eba2 create mode 100644 fuzz/corpus/2225d2f8215c9e415ac6ce0d41855413fa460307 create mode 100644 fuzz/corpus/23c8f61758d49990b5633c3da32e6ad02bbff30c create mode 100644 fuzz/corpus/24ab22a223f470d3c112238c1ee7384614cdf8e0 create mode 100644 fuzz/corpus/25a928530b1982973183c9d1b64cb500d3b54c3c create mode 100644 fuzz/corpus/2934ab98a050eb4187581b73d028d20a2d5beeca create mode 100644 fuzz/corpus/2b12413703657e68436d0a6196461b9fc1333b77 create mode 100644 fuzz/corpus/2bb8fa769be54095af1baefcc4f40d8563d25630 create mode 100644 fuzz/corpus/31af79055f44c1226f87c02ea97bb442d20b5d7f create mode 100644 fuzz/corpus/3371ce6be3d727bc05559e06c5e3014e43972297 create mode 100644 fuzz/corpus/3388e311ce4feda955c6d268047166485e8bc1ef create mode 100644 fuzz/corpus/338e72b519807fd9041fa921ac4dc42f354e064d create mode 100644 fuzz/corpus/33cdae5f3d9e02f549f8d4e69bceb0850190c78d create mode 100644 fuzz/corpus/33db23a38ab67ce204fd304e95d8908fa72ae194 create mode 100644 fuzz/corpus/34e11cb5310343ced27d0d06b3aa716c4927e701 create mode 100644 fuzz/corpus/3526e9257647e436cdbefd57476a0ee7f8d04079 create mode 100644 fuzz/corpus/3539e2d8ddc8acc73d33771dd038ef8279db8a61 create mode 100644 fuzz/corpus/38a5f141a69fc4a7d743f558195c0e11cf01cb09 create mode 100644 fuzz/corpus/3a9387b8cb1f1c49a0225c1d5b017df766622c4c create mode 100644 fuzz/corpus/3a9eccb024e670ba60dd68e6dbc6941d9856009d create mode 100644 fuzz/corpus/3b5aa3f4c1a38f16fb96f03d86f73142490a3977 create mode 100644 fuzz/corpus/3ddf0e90744d3dd73cf395f85fa8864233e58704 create mode 100644 fuzz/corpus/3e2b2f0ab1581461dfc9e0b2b6d33244df8b9507 create mode 100644 fuzz/corpus/3e5432a0f6ec0b3b6577462b5574f8bbdf964020 create mode 100644 fuzz/corpus/3fcbfab37368a03f327a90b9314800eb392f9aa9 create mode 100644 fuzz/corpus/419141f38e7bd8efcf3bc5c55742692a10c050f1 create mode 100644 fuzz/corpus/41b04a983188a907a110c63971b21151c9843843 create mode 100644 fuzz/corpus/469deca0443da8487a9119ab1900f269ab97913b create mode 100644 fuzz/corpus/47d6dc79f407358af11ff1271d0c4a2b4f366e2f create mode 100644 fuzz/corpus/4935117d68863051ef3eee686e3fa335bc85a33b create mode 100644 fuzz/corpus/4c15423f492dcade8bc1f6a4d4df64f20e34bb67 create mode 100644 fuzz/corpus/4cc6c9971bf85188da00d466f88f8407b6761293 create mode 100644 fuzz/corpus/4f4235cc7ef3ba2972e976f9170a4089f4be43b4 create mode 100644 fuzz/corpus/5206b211b425fa5601783562fc254972a5527757 create mode 100644 fuzz/corpus/52a670d56c5a6d7af94c402ca654988587e576d5 create mode 100644 fuzz/corpus/531250e07aa93ce051b3bd354107f4fe8cdb435a create mode 100644 fuzz/corpus/5371a4f527a693ac664c0fd647a5eabc036c5d17 create mode 100644 fuzz/corpus/5521945da7469e0136707f2d1445a170ef6c3f84 create mode 100644 fuzz/corpus/556e1fa17f8b24bb601377ac747ea4479274d59a create mode 100644 fuzz/corpus/56e836645bd178d8f7586ba5277ec58d1359e16a create mode 100644 fuzz/corpus/56f78df0ffeb23e148a0b12acb3ed2b43feed6d9 create mode 100644 fuzz/corpus/57996c03c2e504cb16d7dbcb30f31d3ab7356913 create mode 100644 fuzz/corpus/5b184fd25a784954bbe08ddae81bb85193c0edcf create mode 100644 fuzz/corpus/5c69c00bb03a69f66a68cefe51a7ab9c5729266b create mode 100644 fuzz/corpus/5f9ac4584d79796138ed1b02eb51da20b269d56b create mode 100644 fuzz/corpus/62d74378c462475adc37477b8512f53cb2469943 create mode 100644 fuzz/corpus/63825b8d35cb53f9aa0f8adea417e79e39e9e2a0 create mode 100644 fuzz/corpus/64f13a6846284c580a9038e50dd501e0b9a58408 create mode 100644 fuzz/corpus/65da5e58845e3d63e86765eb54108abb64f8375a create mode 100644 fuzz/corpus/693e002a34afd6bb8dab5772f3bc3d1d3cec210d create mode 100644 fuzz/corpus/6b86233c7df6e2f956777e0483d5854d8a460c39 create mode 100644 fuzz/corpus/6c3f6c108f8cf3e1ddbffb4159038e39b0d0b057 create mode 100644 fuzz/corpus/6ed55b9c0d90d80924c48bf1b11b8103f741926e create mode 100644 fuzz/corpus/6f88ebe387c78c8b302633de4cc1fdffe5f660ca create mode 100644 fuzz/corpus/7161b6ffe9a2efc1c8598dbd496cfcf7034d0043 create mode 100644 fuzz/corpus/722adabc5640a783b2f8f2500f28764b4ac6aaf3 create mode 100644 fuzz/corpus/72549fa4dfc341f9b5aa0369021210d727a25b7d create mode 100644 fuzz/corpus/73ebe48acb4c94ee354584cc54cce01e62868bf7 create mode 100644 fuzz/corpus/744a71d6a17275896f51f084fd56279502086687 create mode 100644 fuzz/corpus/749798e4ffcb312af64c726b60031643c1a7ae4f create mode 100644 fuzz/corpus/75ec53f355a6c3a90cf2dcc24ddbb2446081b9cb create mode 100644 fuzz/corpus/75ed39927daeab8292dc6f6c695e054eefa7f634 create mode 100644 fuzz/corpus/784da0594a769a4cb3e52cb60b9a2cf669b10116 create mode 100644 fuzz/corpus/785ece10aa6b6dfda662f87abef617f3398ac9a6 create mode 100644 fuzz/corpus/7a327da3074102e0539f06bcad19c1e8ce28844a create mode 100644 fuzz/corpus/7ae651f8139ddaaa91220f141f96b2ab0f4f1b1d create mode 100644 fuzz/corpus/7b2ec7e552b0a19d42c7c0c4b7d3e9f0687eba9e create mode 100644 fuzz/corpus/7ba72368458f84a104187d7a7ae98ef9451aa754 create mode 100644 fuzz/corpus/7cec76a63eebb15a620b9f1bb58bcff223629c0d create mode 100644 fuzz/corpus/7f3dc1b701ab60200ac463fc4b57aa4fc498522e create mode 100644 fuzz/corpus/7f895ef6eed5ff4669394fd3b7b864dbde83b36f create mode 100644 fuzz/corpus/83623f2b6453da9f0fe497745853c8df03a5b942 create mode 100644 fuzz/corpus/839c5d2fe334f6bee779a01a6cad244e0bc6ee3a create mode 100644 fuzz/corpus/85c18dd8dc33ea9703ab3b67bd6d976188932ad1 create mode 100644 fuzz/corpus/87b5e15e41d61dcce8befa6be032bf32bc862599 create mode 100644 fuzz/corpus/87e7ac9dbb6aace3fca5e87df7347b4a9b606530 create mode 100644 fuzz/corpus/88f93b9e3bc228dad823fe1fcb9d67776f63d045 create mode 100644 fuzz/corpus/8a2de019e26cd22fe9f797b48c6edbac3b509f1c create mode 100644 fuzz/corpus/8df289206a301da6f097e7108044b817834448fd create mode 100644 fuzz/corpus/8f1eda3de0bf21c6e4ec77af5fdc3a68abaaf6b5 create mode 100644 fuzz/corpus/8faa8c23d29ae9628519eb50d49106580bb49a9e create mode 100644 fuzz/corpus/913fddf15ed755486038346a61da94380885f871 create mode 100644 fuzz/corpus/929510601da41d3b093e08eb172c360b078beb37 create mode 100644 fuzz/corpus/95ca61e0b847c5ca2014598932a87d5f4fd224c3 create mode 100644 fuzz/corpus/95dc062c15738f5547ee1bd184b2bdc9e6863179 create mode 100644 fuzz/corpus/95ece661a83f44d6ad347fe956156935de828310 create mode 100644 fuzz/corpus/962f0f994e9f2f45028be48317a9b099b479c88b create mode 100644 fuzz/corpus/9690f81d995c899149953cfda66c494bfbf9f932 create mode 100644 fuzz/corpus/988ac4cd44d339f917d20329f0b83cb911098134 create mode 100644 fuzz/corpus/9a08160f112708ae57fe800e1a513936b5ff6fed create mode 100644 fuzz/corpus/9b2446528d0cb9316575d3329fca50383a568681 create mode 100644 fuzz/corpus/9b91e3ff93d9576a92fe1611f083f754c2e0c12c create mode 100644 fuzz/corpus/9c3b4a7a3190481d1962e8aaa7ee080ed756e371 create mode 100644 fuzz/corpus/9e696677edd5d0e273e23553b4ee5362f1876f35 create mode 100644 fuzz/corpus/9e891040b46c530baab056ec2e114eaacf34945f create mode 100644 fuzz/corpus/9f9fbb4007d7c8f37d131a919b540889d1d9e4bc create mode 100644 fuzz/corpus/a02172af424a66f6fc9a278213adfa944f7608fd create mode 100644 fuzz/corpus/a03f1dcf20bbdd19ebefe4f80cf38d799c8c00c4 create mode 100644 fuzz/corpus/a0a174d3d10f29c30356e231947b9051c4e6be54 create mode 100644 fuzz/corpus/a0d5afca37acf3d7eea972dd2977f3ffe4a8f37d create mode 100644 fuzz/corpus/a1ba5f16e0e092d24f7857752935b290e0124e72 create mode 100644 fuzz/corpus/a3e78b1df456fd877b9f6179f135a5d98378b29c create mode 100644 fuzz/corpus/a7473834a9451bf3bb31ee5278bba4bdd43a6f1f create mode 100644 fuzz/corpus/a7cdd52296420455fc828ddd761ea103dbb456d0 create mode 100644 fuzz/corpus/a7dacaf428193dae8af833750cef9a6d00b5c773 create mode 100644 fuzz/corpus/a9b7509a44e1cddcd3e79115d15da0fb6084459a create mode 100644 fuzz/corpus/aac03222d9b7a4fb9933e8f65538338cb28d6389 create mode 100644 fuzz/corpus/ab6ad7b89748a1fe481186f091f9e391c426726a create mode 100644 fuzz/corpus/b04cfc32b841d9438740b4aab517588d3cfdbdb5 create mode 100644 fuzz/corpus/b0d538ba10aa6aca3af422156c25e592df549bfa create mode 100644 fuzz/corpus/b0f3fda2e1bf328f1d6f3f1497aa7fa4c02cbf65 create mode 100644 fuzz/corpus/b31db2a9303539638df51abecaea9edc4d0aa660 create mode 100644 fuzz/corpus/b3e2615d6c47bd80f5e5a4b0ed3f208d5628cd20 create mode 100644 fuzz/corpus/b44d71cf10b459b618a5b31186cf92b5cc302bc7 create mode 100644 fuzz/corpus/b5220686b2d4f078319318dcafdcaff665fe6c8d create mode 100644 fuzz/corpus/b6ddeebc1d724c77817a0b9ab5d390e26303e03e create mode 100644 fuzz/corpus/b7336217e23ff6cddc65cb7c798fc71e207bac6d create mode 100644 fuzz/corpus/b78d7aac72fdcec7bb5fede4cdd570287d37ad54 create mode 100644 fuzz/corpus/bb9bf63afed6ba7543f9ff957f03baf383bcd00b create mode 100644 fuzz/corpus/bef08279879afd4e08e0521f0b646877d7037b69 create mode 100644 fuzz/corpus/c0df355f326bb9914e67bf7da788853c914fc704 create mode 100644 fuzz/corpus/c3f035a36c11df93158ed7111b880c3a372ea835 create mode 100644 fuzz/corpus/c3fb0103c6da6d6158209bd99aeca5a359a15639 create mode 100644 fuzz/corpus/c41e90f8c259305e7eef5818f762b7f8363fdb2f create mode 100644 fuzz/corpus/c41efbb0f5b4a095bd3bb1638a8cbfe89ab761d7 create mode 100644 fuzz/corpus/c7ad6adc133f798b5cfff03a27ab95c394c048c0 create mode 100644 fuzz/corpus/c96bb8bdd516bb5cd2f51ea887b02c95974ce850 create mode 100644 fuzz/corpus/ca3971ff6a78ec291e71d633948c5881ee928d57 create mode 100644 fuzz/corpus/cae31911e8672e5d7ca0444eb70aeb86aa0f89c9 create mode 100644 fuzz/corpus/cc30e664354997c9b2eeacc8cf80ebe9d6981232 create mode 100644 fuzz/corpus/ccbc73bfebcc697019281a88d69ed411abd022b3 create mode 100644 fuzz/corpus/ccc9b5c481c7005a2b18c6f7b3895d57055b57c3 create mode 100644 fuzz/corpus/ce778ab2b71c7520a4bf6a53c71ae8788b92abd7 create mode 100644 fuzz/corpus/cece690ab3ae1d247b714f0d31bf47b315d5232d create mode 100644 fuzz/corpus/d0c1f6a6ee9e21381e14d656da926258b063b41d create mode 100644 fuzz/corpus/d2896fed2190b5bd98329d9758c26e5bc441ae5b create mode 100644 fuzz/corpus/d44ae1090f46442bf6f82571122388c07ff2df5b create mode 100644 fuzz/corpus/d643dddfa978b15326ac185fd8592a4064e213a4 create mode 100644 fuzz/corpus/d8cd66165e33ac8171904dec514c4f50ab610cdb create mode 100644 fuzz/corpus/d9f33a1e75a97cc33db614bc02d71d8fd4176ee4 create mode 100644 fuzz/corpus/dadbd79924eef32b6199431701f3c8e7bad9fdcc create mode 100644 fuzz/corpus/de19e810b9e2ebb6b12dd37b5e7d1076f34af5dd create mode 100644 fuzz/corpus/de61430a06e786fa828a1841997ca746f314a50f create mode 100644 fuzz/corpus/df3bc063c169d37389a06837ed46208f1fe1c25b create mode 100644 fuzz/corpus/e0aceb3ef023d2f1af7eb7c8926a1b1df5cdbe89 create mode 100644 fuzz/corpus/e14e7128b5b6eb4fd639e7510a9e58b4fc91fbec create mode 100644 fuzz/corpus/e1a4624b772e1c6f5bc3f85ae05d2853dbaeeceb create mode 100644 fuzz/corpus/e1b5f7e47927e4843e9b029365eb6a5a6e8530d2 create mode 100644 fuzz/corpus/e64ba7edd4532eff9b608d6877c63eb35d3bb65e create mode 100644 fuzz/corpus/e7542ae2ec4ae9324af87522693fa2a84e0258ce create mode 100644 fuzz/corpus/e7bfe09199cdf08f4e43dd7faf1526043aefeb62 create mode 100644 fuzz/corpus/e887d9a2218498334f1f5ca31610312bee121842 create mode 100644 fuzz/corpus/e8e62b69bc04cb5ed30fb7fad6e2a77c320f88f5 create mode 100644 fuzz/corpus/ebca472922552feb96b5a1fb246827e155ef2549 create mode 100644 fuzz/corpus/ec30f45e3fa2f22524a1edf302dd5cf739e2a2e6 create mode 100644 fuzz/corpus/ecbdd50b499c5ee8d76340846bbc3e9ffc20bd4f create mode 100644 fuzz/corpus/ed244dab55c0d6fbb36ab9d4bc33c22f8d7653b0 create mode 100644 fuzz/corpus/ee1e299cce1b26876ce104f944c81abd59233afb create mode 100644 fuzz/corpus/efbf741518ed3a5b72cbff940acf2b34e816ecfb create mode 100644 fuzz/corpus/f08abb06077a2e1699becdfbf16e92d3a54f2fa1 create mode 100644 fuzz/corpus/f2f074dfe49dbe033fe324236aead5176b8938b5 create mode 100644 fuzz/corpus/f404023e17bbf5179c1d2a65d8e5656f60123e17 create mode 100644 fuzz/corpus/f5fb06e95d6695b370477edefb4c300298cbe2cf create mode 100644 fuzz/corpus/f602046b30549b3f62dd5ab123d28094521aa513 create mode 100644 fuzz/corpus/f84127d4aefd8cf967c8d1ad7efc9a7ef0a83fd1 create mode 100644 fuzz/corpus/f87df90d7bc4c3081af67a387f13a2f5e5e7b663 create mode 100644 fuzz/corpus/f961cfb05ce44cfbb80b49108f1c24f203e53008 create mode 100644 fuzz/corpus/f96d3c8ec87eb79a2d5a32e766f2fa364a1787d8 create mode 100644 fuzz/corpus/fa056d3eebf1859a8b702d2520d3f879913ce8d7 create mode 100644 fuzz/corpus/fa253cc79703f60938775baede93c2cab056d6da create mode 100644 fuzz/corpus/fa7622e5400b857832a96fd860653b10c9ba4f52 create mode 100644 fuzz/corpus/fb71d501937402a04cfeca84078922fe59ee75f3 create mode 100644 fuzz/corpus/fb888d425a2cef4158ef3bf0b456dfa9acec78a0 create mode 100644 fuzz/encoder_fuzzer.c create mode 100644 fuzz/parser_fuzzer.c create mode 100644 fuzz/pretty_fuzzer.c create mode 100644 fuzz/tojson_fuzzer.c create mode 100644 fuzz/validate_fuzzer.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 985d0434..2953b067 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ if(WITH_FLOATING_POINT AND NOT WITH_FREESTANDING) option(WITH_CBOR2JSON "Compile code to convert from CBOR to JSON" ON) option(BUILD_EXAMPLES "Compile the TinyCBOR examples" OFF) option(BUILD_TOOLS "Compile the TinyCBOR tools" ON) + option(BUILD_FUZZERS "Compile the TinyCBOR fuzzers (see fuzz/README)" OFF) endif() # Include additional modules that are used unconditionally @@ -217,3 +218,6 @@ endif() if(BUILD_TOOLS) add_subdirectory(tools) endif() +if(BUILD_FUZZERS) + add_subdirectory(fuzz) +endif() diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt new file mode 100644 index 00000000..163b76ec --- /dev/null +++ b/fuzz/CMakeLists.txt @@ -0,0 +1,52 @@ +# /**************************************************************************** +# ** +# ** Copyright (C) 2026 Topogamer0 +# ** +# ** Permission is hereby granted, free of charge, to any person obtaining a copy +# ** of this software and associated documentation files (the "Software"), to deal +# ** in the Software without restriction, including without limitation the rights +# ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# ** copies of the Software, and to permit persons to whom the Software is +# ** furnished to do so, subject to the following conditions: +# ** +# ** The above copyright notice and this permission notice shall be included in +# ** all copies or substantial portions of the Software. +# ** +# ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# ** THE SOFTWARE. +# ** +# ****************************************************************************/ + +include(TinyCBORHelpers) + +# The library and the fuzzers must be compiled with the instrumentation the +# fuzzing engine needs (for libFuzzer, -fsanitize=fuzzer-no-link in +# CMAKE_C_FLAGS) and any sanitizers. LIB_FUZZING_ENGINE is what provides +# main(), as in OSS-Fuzz (which sets it in the environment). +if(DEFINED ENV{LIB_FUZZING_ENGINE}) + set(LIB_FUZZING_ENGINE "$ENV{LIB_FUZZING_ENGINE}" CACHE STRING "Fuzzing engine to link the fuzzers with") +else() + set(LIB_FUZZING_ENGINE "-fsanitize=fuzzer" CACHE STRING "Fuzzing engine to link the fuzzers with") + if(NOT CMAKE_C_FLAGS MATCHES "-fsanitize=[^ ]*fuzzer") + message(WARNING "CMAKE_C_FLAGS has no -fsanitize=fuzzer-no-link: the fuzzers will not be instrumented") + endif() +endif() + +# The fuzzing engines are written in C++ +enable_language(CXX) + +set(fuzzers encoder parser pretty validate) +if(WITH_CBOR2JSON) + list(APPEND fuzzers tojson) +endif() + +foreach(fuzzer ${fuzzers}) + tinycbor_add_executable(${fuzzer}_fuzzer ${fuzzer}_fuzzer.c) + target_link_libraries(${fuzzer}_fuzzer ${LIB_FUZZING_ENGINE}) + set_target_properties(${fuzzer}_fuzzer PROPERTIES LINKER_LANGUAGE CXX) +endforeach() diff --git a/fuzz/README b/fuzz/README new file mode 100644 index 00000000..0d01994c --- /dev/null +++ b/fuzz/README @@ -0,0 +1,40 @@ +TinyCBOR fuzzers +---------------- + +These are libFuzzer-style fuzzers for TinyCBOR, also used by OSS-Fuzz. + + parser_fuzzer parses the input as a sequence of CBOR items, visiting + every item and extracting every value; optionally uses + the reader API (cbor_parser_init_reader) + validate_fuzzer cbor_value_validate() with any combination of flags + tojson_fuzzer cbor_value_to_json_advance() with any combination of flags + pretty_fuzzer cbor_value_to_pretty_advance_flags() and + cbor_value_to_pretty_stream() with any combination of flags + encoder_fuzzer interprets the input as a sequence of encoder commands, + then parses the result back and compares it + +For all fuzzers except encoder_fuzzer, the first 4 bytes of the input are a +configuration word (flags, mode) and the rest is the CBOR payload. The seed +corpus in corpus/ uses a zero configuration word followed by the CBOR data +from the unit tests; cbor.dict is a dictionary for those fuzzers. + +The assert()s in TinyCBOR check that the API is used correctly, so the +fuzzers must be built without NDEBUG: an assertion failure is a bug in the +fuzzer. The fuzzers also abort if the library contradicts its documented +behaviour (for example, if cbor_value_validate() succeeds but parsing the same +data fails). + +To build with Clang and libFuzzer: + + cmake -S. -Bbuild -DBUILD_FUZZERS=ON \ + -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_FLAGS="-g -O1 -fsanitize=fuzzer-no-link,address,undefined" \ + -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" + cmake --build build + +LIB_FUZZING_ENGINE selects what to link the fuzzers with (default: +-fsanitize=fuzzer; if set in the environment, as in OSS-Fuzz, that is used). + +To run: + + build/fuzz/parser_fuzzer -dict=fuzz/cbor.dict new-corpus fuzz/corpus diff --git a/fuzz/cbor.dict b/fuzz/cbor.dict new file mode 100644 index 00000000..ec1dbf10 --- /dev/null +++ b/fuzz/cbor.dict @@ -0,0 +1,105 @@ +# /**************************************************************************** +# ** +# ** Copyright (C) 2026 Topogamer0 +# ** +# ** Permission is hereby granted, free of charge, to any person obtaining a copy +# ** of this software and associated documentation files (the "Software"), to deal +# ** in the Software without restriction, including without limitation the rights +# ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# ** copies of the Software, and to permit persons to whom the Software is +# ** furnished to do so, subject to the following conditions: +# ** +# ** The above copyright notice and this permission notice shall be included in +# ** all copies or substantial portions of the Software. +# ** +# ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# ** THE SOFTWARE. +# ** +# ****************************************************************************/ + +# Initial bytes of CBOR items (RFC 8949), for the parsing fuzzers + +# major type 0: unsigned integers +"\x00" +"\x17" +"\x18" +"\x19" +"\x1a" +"\x1b" +# major type 1: negative integers +"\x20" +"\x37" +"\x38" +"\x39" +"\x3a" +"\x3b" +# major type 2: byte strings +"\x40" +"\x57" +"\x58" +"\x59" +"\x5a" +"\x5b" +"\x5f" +# major type 3: text strings +"\x60" +"\x77" +"\x78" +"\x79" +"\x7a" +"\x7b" +"\x7f" +# major type 4: arrays +"\x80" +"\x97" +"\x98" +"\x99" +"\x9a" +"\x9b" +"\x9f" +# major type 5: maps +"\xa0" +"\xb7" +"\xb8" +"\xb9" +"\xba" +"\xbb" +"\xbf" +# major type 6: tags +"\xc0" +"\xc1" +"\xc2" +"\xc3" +"\xc4" +"\xc5" +"\xd5" +"\xd6" +"\xd7" +"\xd8" +"\xd9" +"\xda" +"\xdb" +"\xd8\x18" +"\xd8\x20" +"\xd9\xd9\xf7" +# major type 7: simple values and floating point +"\xe0" +"\xf4" +"\xf5" +"\xf6" +"\xf7" +"\xf8" +"\xf9" +"\xfa" +"\xfb" +"\xff" +"\xf9\x7c\x00" +"\xf9\xfc\x00" +"\xf9\x7e\x00" +"\xfa\x7f\xc0\x00\x00" +"\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00" diff --git a/fuzz/corpus/014f895dd135e86b9c26361a455ce9bf15a09fda b/fuzz/corpus/014f895dd135e86b9c26361a455ce9bf15a09fda new file mode 100644 index 0000000000000000000000000000000000000000..cb4970e74b791fc8cb627125d911d9962a6b65b5 GIT binary patch literal 32 ncmZQzU|?8SpO}}Jnvj^9n39l`lbZ1VhE_&KVr6kjVsbVBvlk(0002c0BQgL literal 0 HcmV?d00001 diff --git a/fuzz/corpus/0df3f4d23dcecbb7926dee75666404b1e9b67c40 b/fuzz/corpus/0df3f4d23dcecbb7926dee75666404b1e9b67c40 new file mode 100644 index 0000000000000000000000000000000000000000..b4ebb3efe3a5972293d8e79062d1323b13fa2791 GIT binary patch literal 9 QcmZQzU|>l3FrlLv00{sB@Bjb+ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/10cd401ccee82e25d326c9ce0dd6f7419c837a80 b/fuzz/corpus/10cd401ccee82e25d326c9ce0dd6f7419c837a80 new file mode 100644 index 0000000000000000000000000000000000000000..df0ccb74390f3715e2f1031e4da39b367a1f48ed GIT binary patch literal 5 McmZQzU|?_n002b*K>z>% literal 0 HcmV?d00001 diff --git a/fuzz/corpus/13887ac5dc6c08d719daaa094c143f2955e553ef b/fuzz/corpus/13887ac5dc6c08d719daaa094c143f2955e553ef new file mode 100644 index 0000000000000000000000000000000000000000..d5787e7e9619b5b620f072530256a25100edb54c GIT binary patch literal 6 NcmZQzU|=}#4FCds0k;4E literal 0 HcmV?d00001 diff --git a/fuzz/corpus/1409c17079b2428205273f09eedc8df201e40be8 b/fuzz/corpus/1409c17079b2428205273f09eedc8df201e40be8 new file mode 100644 index 0000000000000000000000000000000000000000..c884136e9c71f47841a75da5d1a79ab2f99ccc2e GIT binary patch literal 7 OcmZQzU|?AIoe=;7*#VjW literal 0 HcmV?d00001 diff --git a/fuzz/corpus/15b9bcdcdcaaddd89bec8ed27e3910631837c564 b/fuzz/corpus/15b9bcdcdcaaddd89bec8ed27e3910631837c564 new file mode 100644 index 0000000000000000000000000000000000000000..aa9ce7b9447235a8fd797ce66302bdc14f2b1769 GIT binary patch literal 6 NcmZQzU|=}p0005X0RsR4 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/15cfc192a73e1718c34cae0ec98ff9f66f4997d8 b/fuzz/corpus/15cfc192a73e1718c34cae0ec98ff9f66f4997d8 new file mode 100644 index 0000000000000000000000000000000000000000..6a8afeebf5b13df83270213246f16710ca7cc60a GIT binary patch literal 16 XcmZQzU|?97k&#$gT#}faJ^w!dBq0U> literal 0 HcmV?d00001 diff --git a/fuzz/corpus/199e138c7b38a2936099f37839bd1422fc94bc16 b/fuzz/corpus/199e138c7b38a2936099f37839bd1422fc94bc16 new file mode 100644 index 0000000000000000000000000000000000000000..7765040e6f822ba55699a7ef0abe94b3ffb172d5 GIT binary patch literal 6 NcmZQzU|>k(1ONch0BZmM literal 0 HcmV?d00001 diff --git a/fuzz/corpus/1adb291927afd05380e83f87133422350eab2557 b/fuzz/corpus/1adb291927afd05380e83f87133422350eab2557 new file mode 100644 index 0000000000000000000000000000000000000000..bdedfb3c001b1761f1fd5580423d76c9c9420785 GIT binary patch literal 7 OcmZQzU|{%Z!2kdQVgWJ$ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/1bc07015c76422ba9310425720dee495754458d6 b/fuzz/corpus/1bc07015c76422ba9310425720dee495754458d6 new file mode 100644 index 0000000000000000000000000000000000000000..f21e916068280192fd566d7a5322683d9a5e4b0b GIT binary patch literal 7 OcmZQzU|?u$WB>pHi~$1x literal 0 HcmV?d00001 diff --git a/fuzz/corpus/1bdde59cf453795380dc12a70053a8e5ea05e3d8 b/fuzz/corpus/1bdde59cf453795380dc12a70053a8e5ea05e3d8 new file mode 100644 index 0000000000000000000000000000000000000000..302b451593448d198dab28bf5a863c3675e5155a GIT binary patch literal 32 kcmZQzU|={j0ww literal 0 HcmV?d00001 diff --git a/fuzz/corpus/2225d2f8215c9e415ac6ce0d41855413fa460307 b/fuzz/corpus/2225d2f8215c9e415ac6ce0d41855413fa460307 new file mode 100644 index 0000000000000000000000000000000000000000..9f88e65bbc72a5c2d38acdf7f65eea6f4c65d166 GIT binary patch literal 5 McmZQzU|{$L008>{_W%F@ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/23c8f61758d49990b5633c3da32e6ad02bbff30c b/fuzz/corpus/23c8f61758d49990b5633c3da32e6ad02bbff30c new file mode 100644 index 0000000000000000000000000000000000000000..dff057f9fe34e610a0c48532732ffe8b7ed4e7cb GIT binary patch literal 13 RcmZQzU|^62Vjy5-000330384T literal 0 HcmV?d00001 diff --git a/fuzz/corpus/24ab22a223f470d3c112238c1ee7384614cdf8e0 b/fuzz/corpus/24ab22a223f470d3c112238c1ee7384614cdf8e0 new file mode 100644 index 0000000000000000000000000000000000000000..1de53fc58d05791fc2ef5c3e0d13bb0401b7fd3b GIT binary patch literal 9 OcmZQzU|^8?4+H=Tfdm%- literal 0 HcmV?d00001 diff --git a/fuzz/corpus/25a928530b1982973183c9d1b64cb500d3b54c3c b/fuzz/corpus/25a928530b1982973183c9d1b64cb500d3b54c3c new file mode 100644 index 0000000000000000000000000000000000000000..c21b4bebd640258b401455b92357154515dfadcc GIT binary patch literal 11 ScmZQzU|`svl%L$l@E-sT$pdr% literal 0 HcmV?d00001 diff --git a/fuzz/corpus/2934ab98a050eb4187581b73d028d20a2d5beeca b/fuzz/corpus/2934ab98a050eb4187581b73d028d20a2d5beeca new file mode 100644 index 0000000000000000000000000000000000000000..ef390f08a41cc51bae358c2c5f95835365fed576 GIT binary patch literal 6 NcmZQzU|=|!0005-0VV(d literal 0 HcmV?d00001 diff --git a/fuzz/corpus/2b12413703657e68436d0a6196461b9fc1333b77 b/fuzz/corpus/2b12413703657e68436d0a6196461b9fc1333b77 new file mode 100644 index 0000000000000000000000000000000000000000..f46da7147542cada7bbe2557ada582cec48e001f GIT binary patch literal 9 QcmZQzU|_g;^ZO4401Tf4!T literal 0 HcmV?d00001 diff --git a/fuzz/corpus/3a9387b8cb1f1c49a0225c1d5b017df766622c4c b/fuzz/corpus/3a9387b8cb1f1c49a0225c1d5b017df766622c4c new file mode 100644 index 0000000000000000000000000000000000000000..98a3fc1788e47ada661a00a17b080058150c6742 GIT binary patch literal 15 WcmZQzU|`svl%G7Gfsu*%|9=1)g9MiV literal 0 HcmV?d00001 diff --git a/fuzz/corpus/3a9eccb024e670ba60dd68e6dbc6941d9856009d b/fuzz/corpus/3a9eccb024e670ba60dd68e6dbc6941d9856009d new file mode 100644 index 0000000000000000000000000000000000000000..80d1b212bf25393d9655325e5f32853cebee7b10 GIT binary patch literal 9 QcmZQzU|{%Fe}I7j00}1oIsgCw literal 0 HcmV?d00001 diff --git a/fuzz/corpus/3b5aa3f4c1a38f16fb96f03d86f73142490a3977 b/fuzz/corpus/3b5aa3f4c1a38f16fb96f03d86f73142490a3977 new file mode 100644 index 0000000000000000000000000000000000000000..b0a5b7476bb154f736a9ae6df87603f09f8eb365 GIT binary patch literal 8 PcmZQzU|@)MaQF`Z1H%E| literal 0 HcmV?d00001 diff --git a/fuzz/corpus/3ddf0e90744d3dd73cf395f85fa8864233e58704 b/fuzz/corpus/3ddf0e90744d3dd73cf395f85fa8864233e58704 new file mode 100644 index 0000000000000000000000000000000000000000..907c10ca89fbab74a5610fa12a87688ae0799c74 GIT binary patch literal 8 PcmZQzU|?uUJk$UH1vdgF literal 0 HcmV?d00001 diff --git a/fuzz/corpus/3e2b2f0ab1581461dfc9e0b2b6d33244df8b9507 b/fuzz/corpus/3e2b2f0ab1581461dfc9e0b2b6d33244df8b9507 new file mode 100644 index 0000000000000000000000000000000000000000..48e5df09f0f74be0eea44878dde4c8a49e935475 GIT binary patch literal 7 OcmZQzU|?usU;qFCjR1oH literal 0 HcmV?d00001 diff --git a/fuzz/corpus/3e5432a0f6ec0b3b6577462b5574f8bbdf964020 b/fuzz/corpus/3e5432a0f6ec0b3b6577462b5574f8bbdf964020 new file mode 100644 index 0000000000000000000000000000000000000000..dacad05c22b0ce41b6154f0f5bf07af4664cf269 GIT binary patch literal 8 PcmZQzU|?u!WMBXQ1Cs#+ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/3fcbfab37368a03f327a90b9314800eb392f9aa9 b/fuzz/corpus/3fcbfab37368a03f327a90b9314800eb392f9aa9 new file mode 100644 index 0000000000000000000000000000000000000000..9a60ff659919353c39bef0ff01a7703d3248582b GIT binary patch literal 25 gcmZQzU|?8y@K9P_YHCVO>J6=ojKs>~lEma}0CM38x&QzG literal 0 HcmV?d00001 diff --git a/fuzz/corpus/419141f38e7bd8efcf3bc5c55742692a10c050f1 b/fuzz/corpus/419141f38e7bd8efcf3bc5c55742692a10c050f1 new file mode 100644 index 0000000000000000000000000000000000000000..0e5beb6b70af050e4c747d4f788eb32796b40485 GIT binary patch literal 12 TcmZQzU|=|~D6#5mVkIL06$}Ip literal 0 HcmV?d00001 diff --git a/fuzz/corpus/41b04a983188a907a110c63971b21151c9843843 b/fuzz/corpus/41b04a983188a907a110c63971b21151c9843843 new file mode 100644 index 0000000000000000000000000000000000000000..2d81f98caeeff8cdbdc253559ea30f4086a132ad GIT binary patch literal 7 OcmZQzU|?97zz6^Ws{sQ5 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/469deca0443da8487a9119ab1900f269ab97913b b/fuzz/corpus/469deca0443da8487a9119ab1900f269ab97913b new file mode 100644 index 0000000000000000000000000000000000000000..b4866f477fa7937b7db992f01c9d304fa553dbff GIT binary patch literal 6 NcmZQzU|>jO0002U0Ac_D literal 0 HcmV?d00001 diff --git a/fuzz/corpus/47d6dc79f407358af11ff1271d0c4a2b4f366e2f b/fuzz/corpus/47d6dc79f407358af11ff1271d0c4a2b4f366e2f new file mode 100644 index 0000000000000000000000000000000000000000..7d6f75f9f168b6a47732e5757396307d6d65a7b3 GIT binary patch literal 7 OcmZQzU|>i(v;Y7DQ31sO literal 0 HcmV?d00001 diff --git a/fuzz/corpus/4935117d68863051ef3eee686e3fa335bc85a33b b/fuzz/corpus/4935117d68863051ef3eee686e3fa335bc85a33b new file mode 100644 index 0000000000000000000000000000000000000000..bfd35207886d1c46f3b3429f620542bb79dede66 GIT binary patch literal 12 TcmZQzU|^WPkbz+#BjbMn4D$lx literal 0 HcmV?d00001 diff --git a/fuzz/corpus/4c15423f492dcade8bc1f6a4d4df64f20e34bb67 b/fuzz/corpus/4c15423f492dcade8bc1f6a4d4df64f20e34bb67 new file mode 100644 index 0000000000000000000000000000000000000000..17e3cc86ab086cd06085de3ce83ff5ebf5bac934 GIT binary patch literal 7 OcmZQzU|?AIl@R~~)d83Q literal 0 HcmV?d00001 diff --git a/fuzz/corpus/4cc6c9971bf85188da00d466f88f8407b6761293 b/fuzz/corpus/4cc6c9971bf85188da00d466f88f8407b6761293 new file mode 100644 index 0000000000000000000000000000000000000000..7e60a2ab9fa385a522656d1c60a3e917e2a356b0 GIT binary patch literal 25 bcmZQzU|^`P1`;5^?2(#N1*DmB^8W(>CKCj0 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/4f4235cc7ef3ba2972e976f9170a4089f4be43b4 b/fuzz/corpus/4f4235cc7ef3ba2972e976f9170a4089f4be43b4 new file mode 100644 index 0000000000000000000000000000000000000000..76010dac27090cd5083943aeadf911b31caa72d2 GIT binary patch literal 13 TcmZQzU|`q}gba*~|NjF34*>&z literal 0 HcmV?d00001 diff --git a/fuzz/corpus/5206b211b425fa5601783562fc254972a5527757 b/fuzz/corpus/5206b211b425fa5601783562fc254972a5527757 new file mode 100644 index 0000000000000000000000000000000000000000..ef9d396c457916d6c2dea238b4aeba8c23fa3fa6 GIT binary patch literal 6 NcmZQzU|>l62LJ)a0bl?C literal 0 HcmV?d00001 diff --git a/fuzz/corpus/52a670d56c5a6d7af94c402ca654988587e576d5 b/fuzz/corpus/52a670d56c5a6d7af94c402ca654988587e576d5 new file mode 100644 index 0000000000000000000000000000000000000000..e025cc01987616223d1dba67e326b5c0cd92d060 GIT binary patch literal 43 mcmZQzU|?8u@K8oZVr6kjVsds`UTSJePU^u!P{s`{xD)_$0};^x literal 0 HcmV?d00001 diff --git a/fuzz/corpus/531250e07aa93ce051b3bd354107f4fe8cdb435a b/fuzz/corpus/531250e07aa93ce051b3bd354107f4fe8cdb435a new file mode 100644 index 0000000000000000000000000000000000000000..f688168e33b1a1291201a3c67cd4583be3e4bfb2 GIT binary patch literal 10 RcmZQzU|^WPpMl~3e*g-616=?B literal 0 HcmV?d00001 diff --git a/fuzz/corpus/5371a4f527a693ac664c0fd647a5eabc036c5d17 b/fuzz/corpus/5371a4f527a693ac664c0fd647a5eabc036c5d17 new file mode 100644 index 0000000000000000000000000000000000000000..7d825e101735d999454753b8b0fdc11cb538eb6b GIT binary patch literal 13 PcmZQzU|_KR4*~xGCHn|7 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/5521945da7469e0136707f2d1445a170ef6c3f84 b/fuzz/corpus/5521945da7469e0136707f2d1445a170ef6c3f84 new file mode 100644 index 0000000000000000000000000000000000000000..25b625b9205586b04379a6b76f703f74e9b93ae7 GIT binary patch literal 28 jcmZQzU|?93Sk>6bkd~L4nv#=xLn|XAv9h=%F*zFme?bZr literal 0 HcmV?d00001 diff --git a/fuzz/corpus/556e1fa17f8b24bb601377ac747ea4479274d59a b/fuzz/corpus/556e1fa17f8b24bb601377ac747ea4479274d59a new file mode 100644 index 0000000000000000000000000000000000000000..2fa1b11a12ab25b995cc22260edc104d50eda277 GIT binary patch literal 8 PcmZQzU|=}f#J~su1fu~- literal 0 HcmV?d00001 diff --git a/fuzz/corpus/56e836645bd178d8f7586ba5277ec58d1359e16a b/fuzz/corpus/56e836645bd178d8f7586ba5277ec58d1359e16a new file mode 100644 index 0000000000000000000000000000000000000000..5157c78fd4129b53f623480357c74bf0c26e5bcf GIT binary patch literal 10 RcmZQzU|=|~FtO?&695b)0{{R3 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/56f78df0ffeb23e148a0b12acb3ed2b43feed6d9 b/fuzz/corpus/56f78df0ffeb23e148a0b12acb3ed2b43feed6d9 new file mode 100644 index 0000000000000000000000000000000000000000..b3a931b481ddbcf262ca1d33f88de0a9504d55ff GIT binary patch literal 14 UcmZQzU|=}#+cE$D{|7)803+uGN&o-= literal 0 HcmV?d00001 diff --git a/fuzz/corpus/57996c03c2e504cb16d7dbcb30f31d3ab7356913 b/fuzz/corpus/57996c03c2e504cb16d7dbcb30f31d3ab7356913 new file mode 100644 index 0000000000000000000000000000000000000000..cca8c32cd03e5656501e6013f41a0f1dc0dc8d53 GIT binary patch literal 9 OcmZQzU|^U9#0&rf3jmt{ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/5b184fd25a784954bbe08ddae81bb85193c0edcf b/fuzz/corpus/5b184fd25a784954bbe08ddae81bb85193c0edcf new file mode 100644 index 0000000000000000000000000000000000000000..75a8ee096110fda04807787ffb3548a1ffcc7eed GIT binary patch literal 11 ScmZQzU|?9tu!wk(0ssKg0BisN literal 0 HcmV?d00001 diff --git a/fuzz/corpus/693e002a34afd6bb8dab5772f3bc3d1d3cec210d b/fuzz/corpus/693e002a34afd6bb8dab5772f3bc3d1d3cec210d new file mode 100644 index 0000000000000000000000000000000000000000..3bce4997043b29daebbc4b5fc6d38511b7599134 GIT binary patch literal 14 VcmZQzU|^WPpMl~3en!Us{{b1a1swnY literal 0 HcmV?d00001 diff --git a/fuzz/corpus/6b86233c7df6e2f956777e0483d5854d8a460c39 b/fuzz/corpus/6b86233c7df6e2f956777e0483d5854d8a460c39 new file mode 100644 index 0000000000000000000000000000000000000000..7ce4efbe44d917b88736c7e1c2d9776c42d63530 GIT binary patch literal 15 WcmZQzU|`svl%G7Gf$={R^M3#wd<2&O literal 0 HcmV?d00001 diff --git a/fuzz/corpus/6c3f6c108f8cf3e1ddbffb4159038e39b0d0b057 b/fuzz/corpus/6c3f6c108f8cf3e1ddbffb4159038e39b0d0b057 new file mode 100644 index 0000000000000000000000000000000000000000..7905677f88b207113f64bfcbeb0b190c913250ca GIT binary patch literal 7 OcmZQzU|{%}{vQAYzXD(Y literal 0 HcmV?d00001 diff --git a/fuzz/corpus/6ed55b9c0d90d80924c48bf1b11b8103f741926e b/fuzz/corpus/6ed55b9c0d90d80924c48bf1b11b8103f741926e new file mode 100644 index 0000000000000000000000000000000000000000..bccb830c681fa51197c4b7008b27cd5a55f3b24c GIT binary patch literal 6 NcmZQzU|^{K4*&uK0e=7h literal 0 HcmV?d00001 diff --git a/fuzz/corpus/6f88ebe387c78c8b302633de4cc1fdffe5f660ca b/fuzz/corpus/6f88ebe387c78c8b302633de4cc1fdffe5f660ca new file mode 100644 index 0000000000000000000000000000000000000000..c6c9ad99fe9fb5b18e6835d4262bf6e60f9ba2bb GIT binary patch literal 6 NcmZQzU|=|)0004|0O0@t literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7161b6ffe9a2efc1c8598dbd496cfcf7034d0043 b/fuzz/corpus/7161b6ffe9a2efc1c8598dbd496cfcf7034d0043 new file mode 100644 index 0000000000000000000000000000000000000000..86936f1166c6f00d81bbf7bd21d3bcf85bd09cdc GIT binary patch literal 26 hcmZQzU|?8SpO%-Jnv#>6@c)KZMn+;~aYXDk0lb;%%UzC#q04A6PXaE2J literal 0 HcmV?d00001 diff --git a/fuzz/corpus/72549fa4dfc341f9b5aa0369021210d727a25b7d b/fuzz/corpus/72549fa4dfc341f9b5aa0369021210d727a25b7d new file mode 100644 index 0000000000000000000000000000000000000000..b4cde3991b7122e70046765d6250070716296d9a GIT binary patch literal 12 TcmZQzU|^_ZVD(7N$;k%*33&o@ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/73ebe48acb4c94ee354584cc54cce01e62868bf7 b/fuzz/corpus/73ebe48acb4c94ee354584cc54cce01e62868bf7 new file mode 100644 index 0000000000000000000000000000000000000000..a88f87eead95f96f89ee49a971aa5eba4e4d34c6 GIT binary patch literal 13 QcmZQzU|_JW{|^TL03rJavj6}9 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/744a71d6a17275896f51f084fd56279502086687 b/fuzz/corpus/744a71d6a17275896f51f084fd56279502086687 new file mode 100644 index 0000000000000000000000000000000000000000..79f8f719c995634b8b9bbae9db26191d8c986712 GIT binary patch literal 48 xcmZQzU|^`wa?j6CQOM0N%FE14*HK6Z@e-o<5M2NO literal 0 HcmV?d00001 diff --git a/fuzz/corpus/749798e4ffcb312af64c726b60031643c1a7ae4f b/fuzz/corpus/749798e4ffcb312af64c726b60031643c1a7ae4f new file mode 100644 index 0000000000000000000000000000000000000000..16dd5562efed7542becd7035054b2ffa833e6a8a GIT binary patch literal 11 ScmZQzU|^_V^+?Uh$p-)k_yTeO literal 0 HcmV?d00001 diff --git a/fuzz/corpus/75ec53f355a6c3a90cf2dcc24ddbb2446081b9cb b/fuzz/corpus/75ec53f355a6c3a90cf2dcc24ddbb2446081b9cb new file mode 100644 index 0000000000000000000000000000000000000000..af4d149fdc87dfa5c530118b7a3cdad3b32b2b0c GIT binary patch literal 12 TcmZQzU|^V^>XDk0lm8z85J3a@ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/75ed39927daeab8292dc6f6c695e054eefa7f634 b/fuzz/corpus/75ed39927daeab8292dc6f6c695e054eefa7f634 new file mode 100644 index 0000000000000000000000000000000000000000..dde93897d852659c4f14634b2e6f471f50f5c3c6 GIT binary patch literal 39 hcmZQzU|?93k&#$gT#}faotBrHnv#)X44$A-l literal 0 HcmV?d00001 diff --git a/fuzz/corpus/784da0594a769a4cb3e52cb60b9a2cf669b10116 b/fuzz/corpus/784da0594a769a4cb3e52cb60b9a2cf669b10116 new file mode 100644 index 0000000000000000000000000000000000000000..dc02cd922585b99f621391729ffb683bf3cdc51f GIT binary patch literal 16 XcmZQzU|?97k&#$gT#}faz5hP|Bw+?1 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/785ece10aa6b6dfda662f87abef617f3398ac9a6 b/fuzz/corpus/785ece10aa6b6dfda662f87abef617f3398ac9a6 new file mode 100644 index 0000000000000000000000000000000000000000..a67eeaf601f7577499180b525d09180ff1dd1813 GIT binary patch literal 10 PcmZQzU|_iQ9|#x#6Bq>7 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7a327da3074102e0539f06bcad19c1e8ce28844a b/fuzz/corpus/7a327da3074102e0539f06bcad19c1e8ce28844a new file mode 100644 index 0000000000000000000000000000000000000000..202bfbc412933d154abf3f076003569d3eb6944e GIT binary patch literal 8 PcmZQzU|?97SoH+}1(yPG literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7ae651f8139ddaaa91220f141f96b2ab0f4f1b1d b/fuzz/corpus/7ae651f8139ddaaa91220f141f96b2ab0f4f1b1d new file mode 100644 index 0000000000000000000000000000000000000000..f5cbb924cbfde2c9cf6058c76e6dda810c0c1f83 GIT binary patch literal 48 xcmZQzU|@*Qa?j6CQOM0N%FE14*HK6Z@e-YP5Iq0@ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7b2ec7e552b0a19d42c7c0c4b7d3e9f0687eba9e b/fuzz/corpus/7b2ec7e552b0a19d42c7c0c4b7d3e9f0687eba9e new file mode 100644 index 0000000000000000000000000000000000000000..7cf996b633523748bf313f9e05d2fed129b59824 GIT binary patch literal 9 QcmZQzU|?8ykm)cB00+VXEC2ui literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7ba72368458f84a104187d7a7ae98ef9451aa754 b/fuzz/corpus/7ba72368458f84a104187d7a7ae98ef9451aa754 new file mode 100644 index 0000000000000000000000000000000000000000..3207ad15cec72796993b9c8c4328c700fb9bd15d GIT binary patch literal 5 McmZQzU|{$P008;`_5c6? literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7cec76a63eebb15a620b9f1bb58bcff223629c0d b/fuzz/corpus/7cec76a63eebb15a620b9f1bb58bcff223629c0d new file mode 100644 index 0000000000000000000000000000000000000000..13dd4e027b4bd99f0430c96198e7c9ae6c7b48ee GIT binary patch literal 7 OcmZQzU|?|a$OHfZ#sKsH literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7f3dc1b701ab60200ac463fc4b57aa4fc498522e b/fuzz/corpus/7f3dc1b701ab60200ac463fc4b57aa4fc498522e new file mode 100644 index 0000000000000000000000000000000000000000..fa6d353593580683a8d73cab5a2d7949ebfb5c12 GIT binary patch literal 6 NcmZQzU|{(19{>XN0r&s_ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/7f895ef6eed5ff4669394fd3b7b864dbde83b36f b/fuzz/corpus/7f895ef6eed5ff4669394fd3b7b864dbde83b36f new file mode 100644 index 0000000000000000000000000000000000000000..3f921d4a3a25e5d594a5e45a63167734e85133f2 GIT binary patch literal 8 PcmZQzU|^Wv$nYNk1qK2j literal 0 HcmV?d00001 diff --git a/fuzz/corpus/83623f2b6453da9f0fe497745853c8df03a5b942 b/fuzz/corpus/83623f2b6453da9f0fe497745853c8df03a5b942 new file mode 100644 index 0000000000000000000000000000000000000000..98715f33c2103bf3ccac0329b4ca5a77d83f043a GIT binary patch literal 31 ecmZQzU|?97k&#$gT#}fajbNqarKYCjqyhk@uM3s{ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/839c5d2fe334f6bee779a01a6cad244e0bc6ee3a b/fuzz/corpus/839c5d2fe334f6bee779a01a6cad244e0bc6ee3a new file mode 100644 index 0000000000000000000000000000000000000000..241783620c90a0ced1e053d8a6e144ff6d778980 GIT binary patch literal 6 NcmZQzU|`t)9{>V_0lxqM literal 0 HcmV?d00001 diff --git a/fuzz/corpus/85c18dd8dc33ea9703ab3b67bd6d976188932ad1 b/fuzz/corpus/85c18dd8dc33ea9703ab3b67bd6d976188932ad1 new file mode 100644 index 0000000000000000000000000000000000000000..c8b52b5efb1e3f213a4abc73ff6bf48f64125c44 GIT binary patch literal 7 OcmZQzU|?AIfDr%#s{w-m literal 0 HcmV?d00001 diff --git a/fuzz/corpus/87b5e15e41d61dcce8befa6be032bf32bc862599 b/fuzz/corpus/87b5e15e41d61dcce8befa6be032bf32bc862599 new file mode 100644 index 0000000000000000000000000000000000000000..746e188fd89063c85885d2fc0dd97ef92ff76e1e GIT binary patch literal 17 YcmZQzU|?9(%%I@vk(!f}&zQgf03JdE-~a#s literal 0 HcmV?d00001 diff --git a/fuzz/corpus/87e7ac9dbb6aace3fca5e87df7347b4a9b606530 b/fuzz/corpus/87e7ac9dbb6aace3fca5e87df7347b4a9b606530 new file mode 100644 index 0000000000000000000000000000000000000000..7ea0817b3edb0e7a7cfbaa53e116202f8def2a46 GIT binary patch literal 6 NcmZQzU|=}x0005Z0R#X5 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/88f93b9e3bc228dad823fe1fcb9d67776f63d045 b/fuzz/corpus/88f93b9e3bc228dad823fe1fcb9d67776f63d045 new file mode 100644 index 0000000000000000000000000000000000000000..2793aa7ba76502a84b55ea7c7e643d8931deb98b GIT binary patch literal 5 McmZQzU|>i9003nGVE_OC literal 0 HcmV?d00001 diff --git a/fuzz/corpus/8a2de019e26cd22fe9f797b48c6edbac3b509f1c b/fuzz/corpus/8a2de019e26cd22fe9f797b48c6edbac3b509f1c new file mode 100644 index 0000000000000000000000000000000000000000..eee3ac5129968659a88c6a360cf7a73b1e242c71 GIT binary patch literal 9 QcmZQzU|=|~FtO?j00~$FF#rGn literal 0 HcmV?d00001 diff --git a/fuzz/corpus/8df289206a301da6f097e7108044b817834448fd b/fuzz/corpus/8df289206a301da6f097e7108044b817834448fd new file mode 100644 index 0000000000000000000000000000000000000000..13573e04b6efab9c498c1ad7eb97b21d954db3cb GIT binary patch literal 13 UcmZQzU|?97l%L$fz{tc501&?dU;qFB literal 0 HcmV?d00001 diff --git a/fuzz/corpus/8f1eda3de0bf21c6e4ec77af5fdc3a68abaaf6b5 b/fuzz/corpus/8f1eda3de0bf21c6e4ec77af5fdc3a68abaaf6b5 new file mode 100644 index 0000000000000000000000000000000000000000..ac25cafe94947527246c33f10f2a3bbb5264681f GIT binary patch literal 6 NcmZQzU|_hu000710eAoa literal 0 HcmV?d00001 diff --git a/fuzz/corpus/8faa8c23d29ae9628519eb50d49106580bb49a9e b/fuzz/corpus/8faa8c23d29ae9628519eb50d49106580bb49a9e new file mode 100644 index 0000000000000000000000000000000000000000..303a0f8be47288c5a3c298e6a6a2da59f356e512 GIT binary patch literal 6 NcmZQzU|^WR0003t0GR*) literal 0 HcmV?d00001 diff --git a/fuzz/corpus/913fddf15ed755486038346a61da94380885f871 b/fuzz/corpus/913fddf15ed755486038346a61da94380885f871 new file mode 100644 index 0000000000000000000000000000000000000000..9b521479e4fd7dd23946b1b2f5824b1f32185ae4 GIT binary patch literal 13 UcmZQzU|?9BSjCuF#gxDR01&?dy#N3J literal 0 HcmV?d00001 diff --git a/fuzz/corpus/929510601da41d3b093e08eb172c360b078beb37 b/fuzz/corpus/929510601da41d3b093e08eb172c360b078beb37 new file mode 100644 index 0000000000000000000000000000000000000000..f5e25f52e52d2c6c3d5f41548c4091b44fa883f2 GIT binary patch literal 8 PcmZQzU|_g;^ZNq;2*m@6 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/95ca61e0b847c5ca2014598932a87d5f4fd224c3 b/fuzz/corpus/95ca61e0b847c5ca2014598932a87d5f4fd224c3 new file mode 100644 index 0000000000000000000000000000000000000000..6947110718352f73ab1837b433af50c2361dc8a6 GIT binary patch literal 9 OcmZQzU|`q<#0&rfs{p$I literal 0 HcmV?d00001 diff --git a/fuzz/corpus/95dc062c15738f5547ee1bd184b2bdc9e6863179 b/fuzz/corpus/95dc062c15738f5547ee1bd184b2bdc9e6863179 new file mode 100644 index 0000000000000000000000000000000000000000..f0d1e96daf2bc9bc10f43a566de7c84b7c5161ef GIT binary patch literal 39 ucmZQzU|?97k&#$gT#}fa-I|=AmzrEso}XHhQIwjRl9pdul#-TNmI?q7XAblL literal 0 HcmV?d00001 diff --git a/fuzz/corpus/95ece661a83f44d6ad347fe956156935de828310 b/fuzz/corpus/95ece661a83f44d6ad347fe956156935de828310 new file mode 100644 index 0000000000000000000000000000000000000000..991ec27651f96b76dd5af755e04c7b2067d33a3a GIT binary patch literal 5 McmZQzU|{$T008^|_y7O^ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/962f0f994e9f2f45028be48317a9b099b479c88b b/fuzz/corpus/962f0f994e9f2f45028be48317a9b099b479c88b new file mode 100644 index 0000000000000000000000000000000000000000..70c3f0b52b9369a5b48fb4e7b9d0bfa69135a4ce GIT binary patch literal 25 bcmZQzU|@)k1`;5^?2(!i1*DmB^8W(>AM*qa literal 0 HcmV?d00001 diff --git a/fuzz/corpus/9690f81d995c899149953cfda66c494bfbf9f932 b/fuzz/corpus/9690f81d995c899149953cfda66c494bfbf9f932 new file mode 100644 index 0000000000000000000000000000000000000000..90149c84c473814c493721fef7ec29393f435722 GIT binary patch literal 21 WcmZQzU|?9(nCg+5latQ~rI`ReJ_cF< literal 0 HcmV?d00001 diff --git a/fuzz/corpus/988ac4cd44d339f917d20329f0b83cb911098134 b/fuzz/corpus/988ac4cd44d339f917d20329f0b83cb911098134 new file mode 100644 index 0000000000000000000000000000000000000000..782206960aae928115cb308b9136d6b3a80760df GIT binary patch literal 6 NcmZQzU|?wc1^@y60eAoa literal 0 HcmV?d00001 diff --git a/fuzz/corpus/9a08160f112708ae57fe800e1a513936b5ff6fed b/fuzz/corpus/9a08160f112708ae57fe800e1a513936b5ff6fed new file mode 100644 index 0000000000000000000000000000000000000000..d38ce4e228dab6c16af1039764142e31564cb39a GIT binary patch literal 10 RcmZQzU|_g;^ZQQ*1^^Hw1ET-{ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/9b2446528d0cb9316575d3329fca50383a568681 b/fuzz/corpus/9b2446528d0cb9316575d3329fca50383a568681 new file mode 100644 index 0000000000000000000000000000000000000000..15c0bb60879a2335cb27e203cd464a8d2e9e43f9 GIT binary patch literal 7 OcmZQzU|?AIg%JP)(*c(N literal 0 HcmV?d00001 diff --git a/fuzz/corpus/9b91e3ff93d9576a92fe1611f083f754c2e0c12c b/fuzz/corpus/9b91e3ff93d9576a92fe1611f083f754c2e0c12c new file mode 100644 index 0000000000000000000000000000000000000000..ee268565676c7817a9edb5f418c39393d85c6136 GIT binary patch literal 13 RcmZQzU|{%N{{ct>0RR(d0&4&O literal 0 HcmV?d00001 diff --git a/fuzz/corpus/9c3b4a7a3190481d1962e8aaa7ee080ed756e371 b/fuzz/corpus/9c3b4a7a3190481d1962e8aaa7ee080ed756e371 new file mode 100644 index 0000000000000000000000000000000000000000..7d46072b81234bf0be188e061b412ccd32f18cc1 GIT binary patch literal 6 NcmZQzU|@*<4*&tf0bc+B literal 0 HcmV?d00001 diff --git a/fuzz/corpus/9e696677edd5d0e273e23553b4ee5362f1876f35 b/fuzz/corpus/9e696677edd5d0e273e23553b4ee5362f1876f35 new file mode 100644 index 0000000000000000000000000000000000000000..4271707839691ebbdb724d1fda1e9a4985fb6e91 GIT binary patch literal 17 YcmZQzU|^_E^hiui%t=VhNzDHb03=WaxBvhE literal 0 HcmV?d00001 diff --git a/fuzz/corpus/9e891040b46c530baab056ec2e114eaacf34945f b/fuzz/corpus/9e891040b46c530baab056ec2e114eaacf34945f new file mode 100644 index 0000000000000000000000000000000000000000..6c6c684dd30f7cf532397b651dbe2a4a98232541 GIT binary patch literal 23 ecmZQzU|?97mY15El9PHvDjou;2gy1~dYs literal 0 HcmV?d00001 diff --git a/fuzz/corpus/a0d5afca37acf3d7eea972dd2977f3ffe4a8f37d b/fuzz/corpus/a0d5afca37acf3d7eea972dd2977f3ffe4a8f37d new file mode 100644 index 0000000000000000000000000000000000000000..710dcd54c17130d4bd6ed3666abbab1307ed23fd GIT binary patch literal 8 PcmZQzU|?7%A;ACu0|Wrl literal 0 HcmV?d00001 diff --git a/fuzz/corpus/a1ba5f16e0e092d24f7857752935b290e0124e72 b/fuzz/corpus/a1ba5f16e0e092d24f7857752935b290e0124e72 new file mode 100644 index 0000000000000000000000000000000000000000..f087da4f0a8a6461c891bcf05365bdff0ba857c3 GIT binary patch literal 16 VcmZQzU|@)M^l(gd%mKpu{{R_u1egE- literal 0 HcmV?d00001 diff --git a/fuzz/corpus/a3e78b1df456fd877b9f6179f135a5d98378b29c b/fuzz/corpus/a3e78b1df456fd877b9f6179f135a5d98378b29c new file mode 100644 index 0000000000000000000000000000000000000000..2dace0950c5b57924fdf6d8dc55d8c90be59bc60 GIT binary patch literal 6 NcmZQzU|>k(0RRBh0B!&P literal 0 HcmV?d00001 diff --git a/fuzz/corpus/a7473834a9451bf3bb31ee5278bba4bdd43a6f1f b/fuzz/corpus/a7473834a9451bf3bb31ee5278bba4bdd43a6f1f new file mode 100644 index 0000000000000000000000000000000000000000..830eadb667e1d38f1036625be71d278916aa236a GIT binary patch literal 13 OcmZQzU|_KR4+Q`v{0KAv literal 0 HcmV?d00001 diff --git a/fuzz/corpus/a7cdd52296420455fc828ddd761ea103dbb456d0 b/fuzz/corpus/a7cdd52296420455fc828ddd761ea103dbb456d0 new file mode 100644 index 0000000000000000000000000000000000000000..a5342d7596b7beb0af429a3085601f72ec092228 GIT binary patch literal 8 PcmZQzU|^Wf!0;ac1A_sd literal 0 HcmV?d00001 diff --git a/fuzz/corpus/a7dacaf428193dae8af833750cef9a6d00b5c773 b/fuzz/corpus/a7dacaf428193dae8af833750cef9a6d00b5c773 new file mode 100644 index 0000000000000000000000000000000000000000..d114aa7041389ec6d7062f3daaf171faec198c98 GIT binary patch literal 6 NcmZQzU|>jW0003<0O9}u literal 0 HcmV?d00001 diff --git a/fuzz/corpus/a9b7509a44e1cddcd3e79115d15da0fb6084459a b/fuzz/corpus/a9b7509a44e1cddcd3e79115d15da0fb6084459a new file mode 100644 index 0000000000000000000000000000000000000000..a22db50675f47942b30a3f347be206dae9bc6264 GIT binary patch literal 8 PcmZQzU|?8yAb}A81&sm2 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/aac03222d9b7a4fb9933e8f65538338cb28d6389 b/fuzz/corpus/aac03222d9b7a4fb9933e8f65538338cb28d6389 new file mode 100644 index 0000000000000000000000000000000000000000..3eae8533963cc62190b71ec1397ef8f1e64702aa GIT binary patch literal 13 PcmZQzU|`q{#9#mb2A}}E literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ab6ad7b89748a1fe481186f091f9e391c426726a b/fuzz/corpus/ab6ad7b89748a1fe481186f091f9e391c426726a new file mode 100644 index 0000000000000000000000000000000000000000..e039249dbfc039b47e945e777ef5e8a72a4a77f6 GIT binary patch literal 13 PcmZQzU|@&_VlV&z13&;= literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b04cfc32b841d9438740b4aab517588d3cfdbdb5 b/fuzz/corpus/b04cfc32b841d9438740b4aab517588d3cfdbdb5 new file mode 100644 index 0000000000000000000000000000000000000000..b9e47a3fad724826d950353c70faeeeef95a470d GIT binary patch literal 8 PcmZQzU|?uwWMT#Y0v-U0 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b0d538ba10aa6aca3af422156c25e592df549bfa b/fuzz/corpus/b0d538ba10aa6aca3af422156c25e592df549bfa new file mode 100644 index 0000000000000000000000000000000000000000..f530220d934943421da6c64772586b6c43f12b0b GIT binary patch literal 6 NcmZQzU|>k(1polm0B-;Q literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b0f3fda2e1bf328f1d6f3f1497aa7fa4c02cbf65 b/fuzz/corpus/b0f3fda2e1bf328f1d6f3f1497aa7fa4c02cbf65 new file mode 100644 index 0000000000000000000000000000000000000000..c15ebd524e7c96c2ca4683bcbd4930c6aed7e426 GIT binary patch literal 9 QcmZQzU|^79U}Rtb0052v8~^|S literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b31db2a9303539638df51abecaea9edc4d0aa660 b/fuzz/corpus/b31db2a9303539638df51abecaea9edc4d0aa660 new file mode 100644 index 0000000000000000000000000000000000000000..9eb992227e596888224ffcde0c93d344ca2eb21f GIT binary patch literal 10 RcmZQzU|`tKz`)4(9{>f20l@$O literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b3e2615d6c47bd80f5e5a4b0ed3f208d5628cd20 b/fuzz/corpus/b3e2615d6c47bd80f5e5a4b0ed3f208d5628cd20 new file mode 100644 index 0000000000000000000000000000000000000000..c0fc997e7f2e808f39d65a78cbf2423163e04709 GIT binary patch literal 25 gcmZQzU|?8SpO%-Jnv#?H|AtmZMq*`gNn&y~0B#xywEzGB literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b44d71cf10b459b618a5b31186cf92b5cc302bc7 b/fuzz/corpus/b44d71cf10b459b618a5b31186cf92b5cc302bc7 new file mode 100644 index 0000000000000000000000000000000000000000..78c749c805da985a1690268d2b934ad0a86e1f5d GIT binary patch literal 10 RcmZQzU|>k~NX^N~2LK1}0$Kn7 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b5220686b2d4f078319318dcafdcaff665fe6c8d b/fuzz/corpus/b5220686b2d4f078319318dcafdcaff665fe6c8d new file mode 100644 index 0000000000000000000000000000000000000000..5d11f49048435e082dfdc0a7021d94cb85ab0a54 GIT binary patch literal 5 McmZQzU|?7P005-`p#T5? literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b6ddeebc1d724c77817a0b9ab5d390e26303e03e b/fuzz/corpus/b6ddeebc1d724c77817a0b9ab5d390e26303e03e new file mode 100644 index 0000000000000000000000000000000000000000..dd48a8d62f1a01e42618db597015daed5e589685 GIT binary patch literal 9 QcmZQzU|>l3Frnc900}JvB>(^b literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b7336217e23ff6cddc65cb7c798fc71e207bac6d b/fuzz/corpus/b7336217e23ff6cddc65cb7c798fc71e207bac6d new file mode 100644 index 0000000000000000000000000000000000000000..baa32d1d90284cdc47dc2391ae5a562d697dd926 GIT binary patch literal 6 NcmZQzU|?|k4*&s&0YLx& literal 0 HcmV?d00001 diff --git a/fuzz/corpus/b78d7aac72fdcec7bb5fede4cdd570287d37ad54 b/fuzz/corpus/b78d7aac72fdcec7bb5fede4cdd570287d37ad54 new file mode 100644 index 0000000000000000000000000000000000000000..5ff322289aff014e4e592511b622b03b43890a14 GIT binary patch literal 7 OcmZQzU|=|KAOQdbCjsFA literal 0 HcmV?d00001 diff --git a/fuzz/corpus/bb9bf63afed6ba7543f9ff957f03baf383bcd00b b/fuzz/corpus/bb9bf63afed6ba7543f9ff957f03baf383bcd00b new file mode 100644 index 0000000000000000000000000000000000000000..cccc07ee84d1919a29581fdd8ffe27fbd74619e8 GIT binary patch literal 11 ScmZQzU|?uk$iT3Wkr4n1MFGbE literal 0 HcmV?d00001 diff --git a/fuzz/corpus/bef08279879afd4e08e0521f0b646877d7037b69 b/fuzz/corpus/bef08279879afd4e08e0521f0b646877d7037b69 new file mode 100644 index 0000000000000000000000000000000000000000..d8503fac33d2838bd384f00489e8aeaceeb74caf GIT binary patch literal 30 ZcmZQzU|^__Ff=kYF*P%{urxqr0RT(L1$6)b literal 0 HcmV?d00001 diff --git a/fuzz/corpus/c0df355f326bb9914e67bf7da788853c914fc704 b/fuzz/corpus/c0df355f326bb9914e67bf7da788853c914fc704 new file mode 100644 index 0000000000000000000000000000000000000000..cfa9eeef48d681db7f5a9d4042ef0d886967f05f GIT binary patch literal 16 VcmZQzU|^_E^hiui%mKpu{{SCU1y}$8 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/c3f035a36c11df93158ed7111b880c3a372ea835 b/fuzz/corpus/c3f035a36c11df93158ed7111b880c3a372ea835 new file mode 100644 index 0000000000000000000000000000000000000000..d0affa8c344c8daf3c3e7be3fd6c242e97fee1fa GIT binary patch literal 7 OcmZQzU|_iJr~m*1E&(|J literal 0 HcmV?d00001 diff --git a/fuzz/corpus/c3fb0103c6da6d6158209bd99aeca5a359a15639 b/fuzz/corpus/c3fb0103c6da6d6158209bd99aeca5a359a15639 new file mode 100644 index 0000000000000000000000000000000000000000..e20724dcdd46189545f0e7ed9e020e2b507b793e GIT binary patch literal 8 PcmZQzU|^_ERQL}71ZDyN literal 0 HcmV?d00001 diff --git a/fuzz/corpus/c41e90f8c259305e7eef5818f762b7f8363fdb2f b/fuzz/corpus/c41e90f8c259305e7eef5818f762b7f8363fdb2f new file mode 100644 index 0000000000000000000000000000000000000000..981dec4df9261c142bcc176a83ce12d2bf8d49d9 GIT binary patch literal 7 OcmZQzU|@)3U;qFC5&&8N literal 0 HcmV?d00001 diff --git a/fuzz/corpus/c41efbb0f5b4a095bd3bb1638a8cbfe89ab761d7 b/fuzz/corpus/c41efbb0f5b4a095bd3bb1638a8cbfe89ab761d7 new file mode 100644 index 0000000000000000000000000000000000000000..55468289eb8413d18f3521cd4f759cb268a478ba GIT binary patch literal 9 QcmZQzU|>l3(6FEZ00{j8^#A|> literal 0 HcmV?d00001 diff --git a/fuzz/corpus/c7ad6adc133f798b5cfff03a27ab95c394c048c0 b/fuzz/corpus/c7ad6adc133f798b5cfff03a27ab95c394c048c0 new file mode 100644 index 0000000000000000000000000000000000000000..6bb220b8e53dcdf9050804a59cbcab6a3912dc65 GIT binary patch literal 5 McmZQzU|{$R008&^^Z)<= literal 0 HcmV?d00001 diff --git a/fuzz/corpus/c96bb8bdd516bb5cd2f51ea887b02c95974ce850 b/fuzz/corpus/c96bb8bdd516bb5cd2f51ea887b02c95974ce850 new file mode 100644 index 0000000000000000000000000000000000000000..99b02819095914118e602b142138f9d391465eb2 GIT binary patch literal 11 ScmZQzU|?vhPdt>k;6DHk+XN&4 literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ca3971ff6a78ec291e71d633948c5881ee928d57 b/fuzz/corpus/ca3971ff6a78ec291e71d633948c5881ee928d57 new file mode 100644 index 0000000000000000000000000000000000000000..cbd10bae88f27e5cf23f9a7f118b7c3a9f777856 GIT binary patch literal 9 QcmZQzU|>l3GNGXX00{j8=>Px# literal 0 HcmV?d00001 diff --git a/fuzz/corpus/cae31911e8672e5d7ca0444eb70aeb86aa0f89c9 b/fuzz/corpus/cae31911e8672e5d7ca0444eb70aeb86aa0f89c9 new file mode 100644 index 0000000000000000000000000000000000000000..885ecd998c49c2b8c2087d7c3e07b1d52eaaca1a GIT binary patch literal 6 NcmZQzU|=}#1poqi0kr@C literal 0 HcmV?d00001 diff --git a/fuzz/corpus/cc30e664354997c9b2eeacc8cf80ebe9d6981232 b/fuzz/corpus/cc30e664354997c9b2eeacc8cf80ebe9d6981232 new file mode 100644 index 0000000000000000000000000000000000000000..317ced9f2aa835fd6886df1282a2d56250c999eb GIT binary patch literal 6 NcmZQzU|>j80ssK&0E7Sl literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ccbc73bfebcc697019281a88d69ed411abd022b3 b/fuzz/corpus/ccbc73bfebcc697019281a88d69ed411abd022b3 new file mode 100644 index 0000000000000000000000000000000000000000..59d554c8472c547cf72335b30a7448a843a3359f GIT binary patch literal 7 OcmZQzU|?A2zz6^WYXIW_ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ccc9b5c481c7005a2b18c6f7b3895d57055b57c3 b/fuzz/corpus/ccc9b5c481c7005a2b18c6f7b3895d57055b57c3 new file mode 100644 index 0000000000000000000000000000000000000000..37176a5d74f8cee0fb77b7402b8b74107b5e55cb GIT binary patch literal 9 OcmZQzU|_In01^NLD*(Fy literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ce778ab2b71c7520a4bf6a53c71ae8788b92abd7 b/fuzz/corpus/ce778ab2b71c7520a4bf6a53c71ae8788b92abd7 new file mode 100644 index 0000000000000000000000000000000000000000..01bf3076a1ee05409a76d26a7ac557d616e7333a GIT binary patch literal 9 QcmZQzU|=}V%*ezH00rLxN&o-= literal 0 HcmV?d00001 diff --git a/fuzz/corpus/cece690ab3ae1d247b714f0d31bf47b315d5232d b/fuzz/corpus/cece690ab3ae1d247b714f0d31bf47b315d5232d new file mode 100644 index 0000000000000000000000000000000000000000..bd4f69c114555417be216ea264423689d08d0ddb GIT binary patch literal 8 PcmZQzU|>jou%H0|1@r=B literal 0 HcmV?d00001 diff --git a/fuzz/corpus/d0c1f6a6ee9e21381e14d656da926258b063b41d b/fuzz/corpus/d0c1f6a6ee9e21381e14d656da926258b063b41d new file mode 100644 index 0000000000000000000000000000000000000000..cfce562ef1068f79aa53973ad89112312987178a GIT binary patch literal 27 icmZQzU|?9ZkdbLYT3%{uN>1txt&EJs%Hop5j$0RRCc0KNbK literal 0 HcmV?d00001 diff --git a/fuzz/corpus/d9f33a1e75a97cc33db614bc02d71d8fd4176ee4 b/fuzz/corpus/d9f33a1e75a97cc33db614bc02d71d8fd4176ee4 new file mode 100644 index 0000000000000000000000000000000000000000..98722b1f97c0161bb93feedc3a665f41cbf61fa9 GIT binary patch literal 7 OcmZQzU|_hRm;e9+F#%ct literal 0 HcmV?d00001 diff --git a/fuzz/corpus/dadbd79924eef32b6199431701f3c8e7bad9fdcc b/fuzz/corpus/dadbd79924eef32b6199431701f3c8e7bad9fdcc new file mode 100644 index 0000000000000000000000000000000000000000..7f98e6b6386a75437dd7c16f608b2fbfefbf7b3f GIT binary patch literal 7 OcmZQzU|{%J#{d8W?g4lJ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/de19e810b9e2ebb6b12dd37b5e7d1076f34af5dd b/fuzz/corpus/de19e810b9e2ebb6b12dd37b5e7d1076f34af5dd new file mode 100644 index 0000000000000000000000000000000000000000..1c458cfcc4a6682627a374eeb41e78530fd332c3 GIT binary patch literal 7 OcmZQzU|^7BU;qFBQUDqN literal 0 HcmV?d00001 diff --git a/fuzz/corpus/de61430a06e786fa828a1841997ca746f314a50f b/fuzz/corpus/de61430a06e786fa828a1841997ca746f314a50f new file mode 100644 index 0000000000000000000000000000000000000000..5b874cc3391a4e635be43f3fd8aab3ee6b6a4cc6 GIT binary patch literal 20 bcmZQzU|?97k&#$gT#}fa-O9ko#LNN!Hl76W literal 0 HcmV?d00001 diff --git a/fuzz/corpus/df3bc063c169d37389a06837ed46208f1fe1c25b b/fuzz/corpus/df3bc063c169d37389a06837ed46208f1fe1c25b new file mode 100644 index 0000000000000000000000000000000000000000..0e219a52c1bba31839b00125ed9e622707bf9f94 GIT binary patch literal 6 NcmZQzU|?uW0004K0O9}u literal 0 HcmV?d00001 diff --git a/fuzz/corpus/e0aceb3ef023d2f1af7eb7c8926a1b1df5cdbe89 b/fuzz/corpus/e0aceb3ef023d2f1af7eb7c8926a1b1df5cdbe89 new file mode 100644 index 0000000000000000000000000000000000000000..a63e767ad5bff804fc93cbf2b3ae1f704efefec0 GIT binary patch literal 7 OcmZQzU|?9Nzz6^WD*(d) literal 0 HcmV?d00001 diff --git a/fuzz/corpus/e14e7128b5b6eb4fd639e7510a9e58b4fc91fbec b/fuzz/corpus/e14e7128b5b6eb4fd639e7510a9e58b4fc91fbec new file mode 100644 index 0000000000000000000000000000000000000000..17ec8d913fd2c72d53a959ee963eb84f77071f3c GIT binary patch literal 27 icmZQzU|?8SpOlxHl$w&1lluRLRz^l*WpPPjay9^ejoyPyF81{(r# literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ebca472922552feb96b5a1fb246827e155ef2549 b/fuzz/corpus/ebca472922552feb96b5a1fb246827e155ef2549 new file mode 100644 index 0000000000000000000000000000000000000000..a4e38b44f7aac217934a3f7101ddfd54a13d289f GIT binary patch literal 7 OcmZQzU|=}V_zeIAKLR)a literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ec30f45e3fa2f22524a1edf302dd5cf739e2a2e6 b/fuzz/corpus/ec30f45e3fa2f22524a1edf302dd5cf739e2a2e6 new file mode 100644 index 0000000000000000000000000000000000000000..85b05a260525525b9e5d890167d35b11b13fe877 GIT binary patch literal 8 PcmZQzU|?|eNUa0_11|w; literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ecbdd50b499c5ee8d76340846bbc3e9ffc20bd4f b/fuzz/corpus/ecbdd50b499c5ee8d76340846bbc3e9ffc20bd4f new file mode 100644 index 0000000000000000000000000000000000000000..014aed1942f9b5645693fda89e55d955f9723969 GIT binary patch literal 9 QcmZQzU|{$a-@w2C00-v*+5i9m literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ed244dab55c0d6fbb36ab9d4bc33c22f8d7653b0 b/fuzz/corpus/ed244dab55c0d6fbb36ab9d4bc33c22f8d7653b0 new file mode 100644 index 0000000000000000000000000000000000000000..66ba623df07b0103d3413d03183ec85c1caf3187 GIT binary patch literal 5 McmZQzU|>)L001TcA^-pY literal 0 HcmV?d00001 diff --git a/fuzz/corpus/ee1e299cce1b26876ce104f944c81abd59233afb b/fuzz/corpus/ee1e299cce1b26876ce104f944c81abd59233afb new file mode 100644 index 0000000000000000000000000000000000000000..db676e1799873c7aeeac6ef822690f93adba0924 GIT binary patch literal 6 NcmZQzU|_iJ0005>0T=)P literal 0 HcmV?d00001 diff --git a/fuzz/corpus/efbf741518ed3a5b72cbff940acf2b34e816ecfb b/fuzz/corpus/efbf741518ed3a5b72cbff940acf2b34e816ecfb new file mode 100644 index 0000000000000000000000000000000000000000..6c93a969530edb73825c0f7d705aabb28144ce87 GIT binary patch literal 9 QcmZQzU|?7%AtAv400agA>Hq)$ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/f08abb06077a2e1699becdfbf16e92d3a54f2fa1 b/fuzz/corpus/f08abb06077a2e1699becdfbf16e92d3a54f2fa1 new file mode 100644 index 0000000000000000000000000000000000000000..983c3427fc52ad2cdadbb24df6b41d4abed07170 GIT binary patch literal 6 NcmZQzU|>j80002!0D=Gj literal 0 HcmV?d00001 diff --git a/fuzz/corpus/f2f074dfe49dbe033fe324236aead5176b8938b5 b/fuzz/corpus/f2f074dfe49dbe033fe324236aead5176b8938b5 new file mode 100644 index 0000000000000000000000000000000000000000..d7f6bb70ff51c72dc8825cde1b3c4ec19a4315f2 GIT binary patch literal 7 OcmZQzU|>i(d>;SVg>*K%K%#d literal 0 HcmV?d00001 diff --git a/fuzz/corpus/f5fb06e95d6695b370477edefb4c300298cbe2cf b/fuzz/corpus/f5fb06e95d6695b370477edefb4c300298cbe2cf new file mode 100644 index 0000000000000000000000000000000000000000..2cc8e61d9b2c32ac1c4d3ad0cce0a258e2d47ed5 GIT binary patch literal 14 TcmZQzU|^^MVpfmToSb|B3U>l@ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/f602046b30549b3f62dd5ab123d28094521aa513 b/fuzz/corpus/f602046b30549b3f62dd5ab123d28094521aa513 new file mode 100644 index 0000000000000000000000000000000000000000..a6f34fc8c8c3c33f878c796ce8c9463f03febc7f GIT binary patch literal 10 RcmZQzU|={X73#hJG5`sf0}cQH literal 0 HcmV?d00001 diff --git a/fuzz/corpus/f84127d4aefd8cf967c8d1ad7efc9a7ef0a83fd1 b/fuzz/corpus/f84127d4aefd8cf967c8d1ad7efc9a7ef0a83fd1 new file mode 100644 index 0000000000000000000000000000000000000000..315be7ffd90662130f2ffd04b2d3c1bedba92397 GIT binary patch literal 6 NcmZQzU|^X49{>VF0iOT> literal 0 HcmV?d00001 diff --git a/fuzz/corpus/f87df90d7bc4c3081af67a387f13a2f5e5e7b663 b/fuzz/corpus/f87df90d7bc4c3081af67a387f13a2f5e5e7b663 new file mode 100644 index 0000000000000000000000000000000000000000..ed316a5590284a007f0d7ad77e45dd47b8824f3f GIT binary patch literal 18 VcmZQzU|^^QVh~{UNX^N~2LKFl0(AfY literal 0 HcmV?d00001 diff --git a/fuzz/corpus/f961cfb05ce44cfbb80b49108f1c24f203e53008 b/fuzz/corpus/f961cfb05ce44cfbb80b49108f1c24f203e53008 new file mode 100644 index 0000000000000000000000000000000000000000..9e39b1b3dbb60e1a6bb42a921119721256453acc GIT binary patch literal 26 hcmZQzU|?93ShXN6FEuqKC-sI_Mn+;~aYj5JG literal 0 HcmV?d00001 diff --git a/fuzz/corpus/fa056d3eebf1859a8b702d2520d3f879913ce8d7 b/fuzz/corpus/fa056d3eebf1859a8b702d2520d3f879913ce8d7 new file mode 100644 index 0000000000000000000000000000000000000000..00d7e88540c54b95e84df9febceaa7f657007df9 GIT binary patch literal 5 McmZQzU|?tf004ymfdBvi literal 0 HcmV?d00001 diff --git a/fuzz/corpus/fa253cc79703f60938775baede93c2cab056d6da b/fuzz/corpus/fa253cc79703f60938775baede93c2cab056d6da new file mode 100644 index 0000000000000000000000000000000000000000..3403c6f679247357a139f3c766394a18f1124dac GIT binary patch literal 9 QcmZQzU|?9pz{tP^00TGxrT_o{ literal 0 HcmV?d00001 diff --git a/fuzz/corpus/fa7622e5400b857832a96fd860653b10c9ba4f52 b/fuzz/corpus/fa7622e5400b857832a96fd860653b10c9ba4f52 new file mode 100644 index 0000000000000000000000000000000000000000..9141dfbc515151a526f16eb83766b978036ce151 GIT binary patch literal 8 PcmZQzU|?9taDV{-1PlRU literal 0 HcmV?d00001 diff --git a/fuzz/corpus/fb71d501937402a04cfeca84078922fe59ee75f3 b/fuzz/corpus/fb71d501937402a04cfeca84078922fe59ee75f3 new file mode 100644 index 0000000000000000000000000000000000000000..e11d5e64e08769844c60c717da5de1197f3e5483 GIT binary patch literal 9 QcmZQzU|>i&wBXQ600|NUG5`Po literal 0 HcmV?d00001 diff --git a/fuzz/corpus/fb888d425a2cef4158ef3bf0b456dfa9acec78a0 b/fuzz/corpus/fb888d425a2cef4158ef3bf0b456dfa9acec78a0 new file mode 100644 index 0000000000000000000000000000000000000000..640cf9a32104f70e7df51d13bbcc60fec3da4aad GIT binary patch literal 6 NcmZQzU|=}F0004o0KotN literal 0 HcmV?d00001 diff --git a/fuzz/encoder_fuzzer.c b/fuzz/encoder_fuzzer.c new file mode 100644 index 00000000..36992ebc --- /dev/null +++ b/fuzz/encoder_fuzzer.c @@ -0,0 +1,728 @@ +/**************************************************************************** +** +** Copyright (C) 2026 Topogamer0 +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +/* + * Fuzzes the encoder API. The input is a program: after two configuration + * bytes, each byte is a command (low nibble) with a small argument (high + * nibble), optionally followed by operand bytes. See run_program() for the + * command list. + * + * The program is run with an output buffer of the size given in the + * configuration; if that buffer was too small, it is run again with the size + * that cbor_encoder_get_extra_bytes_needed() asked for. It is also run with a + * writer function. All runs must produce the same bytes, which are then + * parsed back, validated, and compared to what the program encoded. + */ + +#include "cbor.h" + +#include +#include +#include +#include + +#ifdef NDEBUG +# error "The fuzzers must be built without NDEBUG: TinyCBOR's assertions check the API usage" +#endif + +#define MAX_NESTING 256 + +/* Nested containers and chained tags must stay within the parser's limit + * (CBOR_PARSER_MAX_RECURSIONS, 1024) for the result to be parsed back */ +#define MAX_TAGS 512 + +/* Abort on a result that contradicts the documented behavior */ +#define CHECK(cond) do { if (!(cond)) abort(); } while (0) + +enum Command { + CmdUInt = 0, + CmdNegativeInt, + CmdInt, + CmdSimpleValue, + CmdBooleanNullUndefined, + CmdTag, + CmdTextString, + CmdByteString, + CmdHalfFloat, + CmdFloat, + CmdDouble, + CmdFloatAsHalfFloat, + CmdCreateArray, + CmdCreateMap, + CmdCloseContainer, + CmdRaw +}; + +/* what the program encoded, to be compared with what is parsed back */ +enum EventType { + EventInteger, + EventNegativeInteger, + EventSimple, /* includes booleans, null and undefined */ + EventTag, + EventString, + EventHalfFloat, + EventFloatAsHalfFloat, /* cbor_encode_float_as_half_float(): value is the float */ + EventFloat, + EventDouble, + EventArray, + EventMap, + EventEnd +}; + +struct Event +{ + enum EventType type; + CborType string_type; + bool indefinite; + uint64_t value; /* value, bit pattern, length or number of pairs */ + const uint8_t *data; /* string contents */ +}; + +struct Input +{ + const uint8_t *ptr; + const uint8_t *end; +}; + +struct Level +{ + CborEncoder encoder; + size_t length; /* declared number of items (pairs for maps) */ + size_t count; /* number of items written, tags excluded */ + bool map; + bool tag_pending; +}; + +struct WriterOutput +{ + uint8_t *data; + size_t size; + int command; /* the command being run, to check the append type */ +}; + +struct Run +{ + struct Level levels[MAX_NESTING + 1]; + int depth; + int tags; + struct WriterOutput *writer; + + struct Event *events; + size_t event_count; + size_t event_capacity; + bool record_events; + + CborError error; /* first error other than CborErrorOutOfMemory */ + bool out_of_memory; + bool used_raw; +}; + +static uint8_t get_byte(struct Input *in) +{ + return in->ptr < in->end ? *in->ptr++ : 0; +} + +static uint64_t get_number(struct Input *in, unsigned bytes) +{ + uint64_t v = 0; + while (bytes--) + v = (v << 8) | get_byte(in); + return v; +} + +/* small immediates (< 8) or 1, 2, 4 or 8 bytes from the input */ +static uint64_t get_value(struct Input *in, unsigned arg) +{ + if (arg < 8) + return arg; + return get_number(in, 1U << (arg & 3)); +} + +static size_t get_data(struct Input *in, unsigned arg, const uint8_t **data) +{ + size_t len = arg < 15 ? arg : (size_t)get_number(in, 2); + size_t available = (size_t)(in->end - in->ptr); + if (len > available) + len = available; + *data = in->ptr; + in->ptr += len; + return len; +} + +static CborError writer_function(void *token, const void *data, size_t len, CborEncoderAppendType type) +{ + struct WriterOutput *out = (struct WriterOutput *)token; + uint8_t *ptr; + + switch (type) { + case CborEncoderAppendCborData: + CHECK(out->command != CmdRaw); + break; + case CborEncoderAppendStringData: + CHECK(out->command == CmdTextString || out->command == CmdByteString); + break; + case CborEncoderAppendRawData: + CHECK(out->command == CmdRaw); + break; + default: + abort(); + } + + if (len == 0) + return CborNoError; + ptr = (uint8_t *)realloc(out->data, out->size + len); + if (!ptr) + return CborErrorOutOfMemory; + memcpy(ptr + out->size, data, len); + out->data = ptr; + out->size += len; + return CborNoError; +} + +static void record(struct Run *run, enum EventType type, uint64_t value) +{ + struct Event *ev; + if (!run->record_events) + return; + if (run->event_count == run->event_capacity) { + run->event_capacity = run->event_capacity ? 2 * run->event_capacity : 64; + run->events = (struct Event *)realloc(run->events, run->event_capacity * sizeof(struct Event)); + CHECK(run->events); + } + ev = &run->events[run->event_count++]; + memset(ev, 0, sizeof(*ev)); + ev->type = type; + ev->value = value; +} + +/* returns false if the program must stop */ +static bool check_error(struct Run *run, CborError err) +{ + if (err == CborErrorOutOfMemory) { + /* documented as recoverable: the encoder keeps counting */ + run->out_of_memory = true; + return true; + } + if (err) { + run->error = err; + return false; + } + return true; +} + +static void item_added(struct Run *run) +{ + struct Level *level = &run->levels[run->depth]; + if (level->tag_pending) + level->tag_pending = false; + ++level->count; +} + +static bool encode_null(struct Run *run) +{ + record(run, EventSimple, CborNullType & 0x1f); + item_added(run); + return check_error(run, cbor_encode_null(&run->levels[run->depth].encoder)); +} + +static bool close_container(struct Run *run) +{ + struct Level *level = &run->levels[run->depth]; + size_t needed = level->map ? 2 * level->length : level->length; + CborError err; + + /* complete what we can, so the result is more often valid CBOR */ + if (level->tag_pending && !encode_null(run)) + return false; + if (level->length == CborIndefiniteLength) { + if (level->map && level->count % 2 && !encode_null(run)) + return false; + } else if (level->count < needed && needed - level->count <= 16) { + while (level->count < needed) { + if (!encode_null(run)) + return false; + } + } + + record(run, EventEnd, 0); + --run->depth; + err = cbor_encoder_close_container(&run->levels[run->depth].encoder, &level->encoder); + return check_error(run, err); +} + +static bool create_container(struct Run *run, bool map, unsigned arg, struct Input *in) +{ + struct Level *parent = &run->levels[run->depth]; + struct Level *level; + size_t length; + CborError err; + + if (arg < 14) + length = arg; + else if (arg == 14) + length = CborIndefiniteLength; + else + length = (size_t)get_number(in, 8); + if (run->depth == MAX_NESTING) + return true; + level = &run->levels[run->depth + 1]; + memset(level, 0, sizeof(*level)); + level->length = length; + level->map = map; + + if (map) + err = cbor_encoder_create_map(&parent->encoder, &level->encoder, length); + else + err = cbor_encoder_create_array(&parent->encoder, &level->encoder, length); + if (!check_error(run, err)) + return false; + + record(run, map ? EventMap : EventArray, length); + if (run->record_events) + run->events[run->event_count - 1].indefinite = length == CborIndefiniteLength; + item_added(run); + ++run->depth; + return true; +} + +/* Runs the whole program on the encoder in run->levels[0] */ +static void run_program(struct Run *run, struct Input in) +{ + while (in.ptr < in.end) { + struct Level *level = &run->levels[run->depth]; + CborEncoder *encoder = &level->encoder; + uint8_t command = get_byte(&in); + unsigned arg = command >> 4; + const uint8_t *data; + size_t len; + uint64_t v; + uint8_t u8; + uint16_t u16; + uint32_t u32; + float f; + CborError err = CborNoError; + + if (run->writer) + run->writer->command = command & 0xf; + + switch (command & 0xf) { + case CmdUInt: + v = get_value(&in, arg); + record(run, EventInteger, v); + err = cbor_encode_uint(encoder, v); + item_added(run); + break; + + case CmdNegativeInt: + /* zero encodes -2^64 */ + v = get_value(&in, arg); + record(run, EventNegativeInteger, v - 1); + err = cbor_encode_negative_int(encoder, v); + item_added(run); + break; + + case CmdInt: + v = get_value(&in, arg); + if (arg & 4) + v = ~v; /* make it negative */ + if ((int64_t)v < 0) + record(run, EventNegativeInteger, ~v); + else + record(run, EventInteger, v); + err = cbor_encode_int(encoder, (int64_t)v); + item_added(run); + break; + + case CmdSimpleValue: + /* 25 to 31 are rejected with CborErrorIllegalSimpleType; 24 is + * accepted but can't be encoded as well-formed CBOR */ + u8 = get_byte(&in); + if (u8 == 24) + break; + record(run, EventSimple, u8); + err = cbor_encode_simple_value(encoder, u8); + item_added(run); + break; + + case CmdBooleanNullUndefined: + switch (arg & 3) { + case 0: + record(run, EventSimple, (CborBooleanType & 0x1f) - 1); + err = cbor_encode_boolean(encoder, false); + break; + case 1: + record(run, EventSimple, CborBooleanType & 0x1f); + err = cbor_encode_boolean(encoder, true); + break; + case 2: + record(run, EventSimple, CborNullType & 0x1f); + err = cbor_encode_null(encoder); + break; + case 3: + record(run, EventSimple, CborUndefinedType & 0x1f); + err = cbor_encode_undefined(encoder); + break; + } + item_added(run); + break; + + case CmdTag: + v = get_value(&in, arg); + if (++run->tags > MAX_TAGS) + break; + record(run, EventTag, v); + err = cbor_encode_tag(encoder, v); + level->tag_pending = true; + break; + + case CmdTextString: + case CmdByteString: + len = get_data(&in, arg, &data); + record(run, EventString, len); + if (run->record_events) { + struct Event *ev = &run->events[run->event_count - 1]; + ev->data = data; + ev->string_type = (command & 0xf) == CmdTextString ? CborTextStringType : CborByteStringType; + } + if ((command & 0xf) == CmdTextString) + err = cbor_encode_text_string(encoder, (const char *)data, len); + else + err = cbor_encode_byte_string(encoder, data, len); + item_added(run); + break; + + case CmdHalfFloat: + u16 = (uint16_t)get_number(&in, 2); + record(run, EventHalfFloat, u16); + err = cbor_encode_half_float(encoder, &u16); + item_added(run); + break; + + case CmdFloat: + u32 = (uint32_t)get_number(&in, 4); + memcpy(&f, &u32, sizeof(f)); + record(run, EventFloat, u32); + err = cbor_encode_float(encoder, f); + item_added(run); + break; + + case CmdDouble: { + double d; + v = get_number(&in, 8); + memcpy(&d, &v, sizeof(d)); + record(run, EventDouble, v); + err = cbor_encode_double(encoder, d); + item_added(run); + break; + } + + case CmdFloatAsHalfFloat: + u32 = (uint32_t)get_number(&in, 4); + memcpy(&f, &u32, sizeof(f)); + /* the value must be representable as half-precision */ + if (!isnan(f) && !isinf(f) && fabsf(f) > 65504.f) + break; + record(run, EventFloatAsHalfFloat, u32); + err = cbor_encode_float_as_half_float(encoder, f); + item_added(run); + break; + + case CmdCreateArray: + case CmdCreateMap: + if (!create_container(run, (command & 0xf) == CmdCreateMap, arg, &in)) + return; + continue; + + case CmdCloseContainer: + if (run->depth && !close_container(run)) + return; + continue; + + case CmdRaw: + /* arbitrary bytes: the result may not be valid CBOR any more */ + len = get_data(&in, arg, &data); + run->used_raw = true; + err = cbor_encode_raw(encoder, data, len); + break; + } + + if (!check_error(run, err)) + return; + } + + if (run->writer) + run->writer->command = CmdCloseContainer; + while (run->depth) { + if (!close_container(run)) + return; + } + if (run->levels[0].tag_pending) + encode_null(run); +} + +static double half_to_double(uint16_t half) +{ + int exponent = (half >> 10) & 0x1f; + int mantissa = half & 0x3ff; + double d; + if (exponent == 0) + d = ldexp(mantissa, -24); + else if (exponent == 0x1f) + d = mantissa ? NAN : INFINITY; + else + d = ldexp(mantissa + 1024, exponent - 25); + return half & 0x8000 ? -d : d; +} + +/* f was in range, so the result must be within half a unit in the last place */ +static void check_half_conversion(float f, uint16_t half) +{ + double d = half_to_double(half); + if (isnan(f)) { + CHECK(isnan(d)); + } else if (isinf(f)) { + CHECK(d == f); + } else { + int exponent = f == 0 ? -14 : ilogb(f); + CHECK(fabs(d - f) <= ldexp(1, (exponent < -14 ? -14 : exponent) - 11)); + CHECK(d == 0 || !signbit(d) == !signbit(f)); + } +} + +static size_t parse_back(CborValue *it, const struct Event *events, size_t count, size_t i, int nesting); + +static size_t parse_back_one(CborValue *it, const struct Event *events, size_t count, size_t i, int nesting) +{ + const struct Event *ev; + CborValue recursed; + uint64_t v; + uint16_t u16; + float f; + double d; + uint8_t *buffer; + size_t len; + bool b; + + CHECK(i < count); + ev = &events[i++]; + switch (cbor_value_get_type(it)) { + case CborIntegerType: + CHECK(ev->type == (cbor_value_is_negative_integer(it) ? EventNegativeInteger : EventInteger)); + cbor_value_get_raw_integer(it, &v); + CHECK(v == ev->value); + break; + + case CborSimpleType: { + uint8_t simple; + CHECK(ev->type == EventSimple); + cbor_value_get_simple_type(it, &simple); + CHECK(simple == ev->value); + break; + } + + case CborBooleanType: + CHECK(ev->type == EventSimple); + cbor_value_get_boolean(it, &b); + CHECK(ev->value == (CborBooleanType & 0x1f) - 1U + b); + break; + + case CborNullType: + case CborUndefinedType: + CHECK(ev->type == EventSimple && ev->value == (cbor_value_get_type(it) & 0x1fU)); + break; + + case CborTagType: + CHECK(ev->type == EventTag); + cbor_value_get_tag(it, &v); + CHECK(v == ev->value); + break; + + case CborHalfFloatType: + CHECK(ev->type == EventHalfFloat || ev->type == EventFloatAsHalfFloat); + cbor_value_get_half_float(it, &u16); + if (ev->type == EventHalfFloat) { + CHECK(u16 == ev->value); + } else { + uint32_t u32 = (uint32_t)ev->value; + memcpy(&f, &u32, sizeof(f)); + check_half_conversion(f, u16); + } + break; + + case CborFloatType: + CHECK(ev->type == EventFloat); + cbor_value_get_float(it, &f); + memcpy(&v, &f, sizeof(f)); + CHECK((uint32_t)v == ev->value); + break; + + case CborDoubleType: + CHECK(ev->type == EventDouble); + cbor_value_get_double(it, &d); + memcpy(&v, &d, sizeof(d)); + CHECK(v == ev->value); + break; + + case CborByteStringType: + case CborTextStringType: + CHECK(ev->type == EventString && ev->string_type == cbor_value_get_type(it)); + CHECK(cbor_value_is_length_known(it)); + if (cbor_value_is_text_string(it)) + CHECK(cbor_value_dup_text_string(it, (char **)&buffer, &len, it) == CborNoError); + else + CHECK(cbor_value_dup_byte_string(it, &buffer, &len, it) == CborNoError); + CHECK(len == ev->value); + CHECK(len == 0 || memcmp(buffer, ev->data, len) == 0); + free(buffer); + return i; + + case CborArrayType: + case CborMapType: + CHECK(ev->type == (cbor_value_is_map(it) ? EventMap : EventArray)); + CHECK(cbor_value_is_length_known(it) == !ev->indefinite); + if (!ev->indefinite) { + if (cbor_value_is_map(it)) + CHECK(cbor_value_get_map_length(it, &len) == CborNoError); + else + CHECK(cbor_value_get_array_length(it, &len) == CborNoError); + CHECK(len == ev->value); + } + CHECK(nesting > 0); + CHECK(cbor_value_enter_container(it, &recursed) == CborNoError); + i = parse_back(&recursed, events, count, i, nesting - 1); + CHECK(i < count && events[i].type == EventEnd); + CHECK(cbor_value_leave_container(it, &recursed) == CborNoError); + return i + 1; + + default: + abort(); + } + + CHECK(cbor_value_advance_fixed(it) == CborNoError); + return i; +} + +static size_t parse_back(CborValue *it, const struct Event *events, size_t count, size_t i, int nesting) +{ + while (!cbor_value_at_end(it)) + i = parse_back_one(it, events, count, i, nesting); + return i; +} + +static void free_run(struct Run *run) +{ + free(run->events); +} + +static void init_run(struct Run *run, bool record_events) +{ + memset(run, 0, sizeof(*run)); + run->record_events = record_events; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + static struct Run run, writer_run; + struct Input in; + struct WriterOutput writer_output = { NULL, 0, -1 }; + uint8_t *buffer; + size_t buffer_size; + size_t used; + const uint8_t *ptr; + const uint8_t *end; + + if (size < 2) + return 0; + buffer_size = data[0] | (data[1] & 0x0f) << 8; + in.ptr = data + 2; + in.end = data + size; + + /* first run, with a buffer that is possibly too small */ + init_run(&run, true); + buffer = (uint8_t *)malloc(buffer_size); + CHECK(buffer || buffer_size == 0); + cbor_encoder_init(&run.levels[0].encoder, buffer, buffer_size, 0); + run_program(&run, in); + + if (run.error == CborNoError && run.out_of_memory) { + /* "Returns how many more bytes the original buffer [...] needs to be + * extended by so that no CborErrorOutOfMemory condition will happen" */ + size_t extra = cbor_encoder_get_extra_bytes_needed(&run.levels[0].encoder); + CHECK(extra > 0); + buffer_size += extra; + free(buffer); + free_run(&run); + + init_run(&run, true); + buffer = (uint8_t *)malloc(buffer_size); + CHECK(buffer); + cbor_encoder_init(&run.levels[0].encoder, buffer, buffer_size, 0); + run_program(&run, in); + CHECK(!run.out_of_memory); + CHECK(cbor_encoder_get_buffer_size(&run.levels[0].encoder, buffer) == buffer_size); + } + + /* the same program with a writer function */ + init_run(&writer_run, false); + writer_run.writer = &writer_output; + cbor_encoder_init_writer(&writer_run.levels[0].encoder, writer_function, &writer_output); + run_program(&writer_run, in); + CHECK(writer_run.error == run.error); + CHECK(!writer_run.out_of_memory); + + if (run.error == CborNoError) { + used = cbor_encoder_get_buffer_size(&run.levels[0].encoder, buffer); + CHECK(cbor_encoder_get_extra_bytes_needed(&run.levels[0].encoder) == 0); + CHECK(writer_output.size == used); + CHECK(used == 0 || memcmp(writer_output.data, buffer, used) == 0); + } + + if (run.error == CborNoError && !run.used_raw) { + /* parse it back: it's a sequence of items. The encoder always uses + * the shortest encoding for integers and lengths; parse_back() + * checks that indeterminate length was used where requested. */ + size_t i = 0; + + ptr = buffer; + end = buffer + used; + while (ptr < end) { + CborParser parser; + CborValue it; + CborError err; + CHECK(cbor_parser_init(ptr, (size_t)(end - ptr), 0, &parser, &it) == CborNoError); + err = cbor_value_validate(&it, CborValidateShortestIntegrals); + CHECK(err == CborNoError); + i = parse_back(&it, run.events, run.event_count, i, MAX_NESTING); + CHECK(cbor_value_get_next_byte(&it) > ptr); + ptr = cbor_value_get_next_byte(&it); + } + CHECK(i == run.event_count); + } + + free(writer_output.data); + free(buffer); + free_run(&run); + free_run(&writer_run); + return 0; +} diff --git a/fuzz/parser_fuzzer.c b/fuzz/parser_fuzzer.c new file mode 100644 index 00000000..8119987c --- /dev/null +++ b/fuzz/parser_fuzzer.c @@ -0,0 +1,525 @@ +/**************************************************************************** +** +** Copyright (C) 2026 Topogamer0 +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +/* + * Fuzzes the parser API: the input is decoded as a sequence of CBOR items and + * every item is visited, including those nested inside arrays, maps and tags, + * extracting each value with the corresponding cbor_value_get_* function. + * + * The first 4 bytes of the input are a configuration word (see FuzzConfig); + * the rest is the CBOR payload. + */ + +#include "cbor.h" + +#include +#include +#include + +#ifdef NDEBUG +# error "The fuzzers must be built without NDEBUG: TinyCBOR's assertions check the API usage" +#endif + +/* Bounds the harness' own recursion. The library has its own limit + * (CBOR_PARSER_MAX_RECURSIONS) for the functions that recurse. */ +#define MAX_NESTING 1024 + +/* Cross-checks whose cost is proportional to the size of the item (instead + * of being constant per item) are limited, so the total time stays linear in + * the size of the input */ +#define MAX_EXPENSIVE_CHECKS 16 + +enum FuzzConfig { + /* use cbor_parser_init_reader() instead of cbor_parser_init() */ + ConfigUseReader = 0x01, + + /* reader only: make the first item visible one byte at a time, calling + * cbor_value_reparse() after each CborErrorUnexpectedEOF */ + ConfigIncremental = 0x02, + + /* reader only: skip containers with cbor_value_advance() and read + * strings with cbor_value_copy_*_string() instead of chunk by chunk */ + ConfigReaderAdvance = 0x04 +}; + +/* Abort on a result that is inconsistent with another API's result: if + * this triggers, the library disagrees with itself. */ +#define CHECK(cond) do { if (!(cond)) abort(); } while (0) + +/* keeps the decoded values from being optimized out */ +static volatile uint64_t sink; + +struct ReaderInput +{ + const uint8_t *data; + size_t size; /* how much of the data is visible to the parser */ + size_t consumed; +}; + +struct Context +{ + bool reader; + bool reader_advance; + int expensive_checks; + uint8_t *buffer; /* for cbor_value_copy_*_string() in reader mode */ + size_t buffer_size; +}; + +static bool reader_can_read_bytes(void *token, size_t len) +{ + struct ReaderInput *input = (struct ReaderInput *)token; + return input->size - input->consumed >= len; +} + +static void *reader_read_bytes(void *token, void *dst, size_t offset, size_t len) +{ + struct ReaderInput *input = (struct ReaderInput *)token; + size_t available = input->size - input->consumed; + + /* the library must have checked with can_read_bytes() first */ + CHECK(offset <= available && len <= available - offset); + return memcpy(dst, input->data + input->consumed + offset, len); +} + +static void reader_advance_bytes(void *token, size_t len) +{ + struct ReaderInput *input = (struct ReaderInput *)token; + CHECK(len <= input->size - input->consumed); + input->consumed += len; +} + +static CborError reader_transfer_string(void *token, const void **userptr, size_t offset, size_t len) +{ + struct ReaderInput *input = (struct ReaderInput *)token; + size_t available = input->size - input->consumed; + if (offset > available || len > available - offset) + return CborErrorUnexpectedEOF; + input->consumed += offset; + *userptr = input->data + input->consumed; + input->consumed += len; + return CborNoError; +} + +static const struct CborParserOperations reader_ops = { + reader_can_read_bytes, + reader_read_bytes, + reader_advance_bytes, + reader_transfer_string +}; + +static bool expensive_check(struct Context *ctx) +{ + if (ctx->expensive_checks == 0) + return false; + --ctx->expensive_checks; + return true; +} + +static uint64_t checksum(const void *ptr, size_t len) +{ + const uint8_t *bytes = (const uint8_t *)ptr; + uint64_t sum = 0; + while (len--) + sum = sum * 31 + *bytes++; + return sum; +} + +static CborError get_string_chunk(CborValue *it, const void **ptr, size_t *len) +{ + if (cbor_value_is_text_string(it)) + return cbor_value_get_text_string_chunk(it, (const char **)ptr, len, it); + return cbor_value_get_byte_string_chunk(it, (const uint8_t **)ptr, len, it); +} + +static CborError copy_string(const CborValue *it, void *buffer, size_t *len, CborValue *next) +{ + if (cbor_value_is_text_string(it)) + return cbor_value_copy_text_string(it, (char *)buffer, len, next); + return cbor_value_copy_byte_string(it, (uint8_t *)buffer, len, next); +} + +static CborError parse_value(struct Context *ctx, CborValue *it, int nesting); + +static void parse_integer(const CborValue *it) +{ + uint64_t raw, u64; + int64_t i64, i64_unchecked; + int i, i_unchecked; + + cbor_value_get_raw_integer(it, &raw); + sink += raw; + if (cbor_value_is_unsigned_integer(it)) { + cbor_value_get_uint64(it, &u64); + CHECK(u64 == raw); + } else { + CHECK(cbor_value_is_negative_integer(it)); + } + + /* compare with the unchecked getters where the value fits */ + if (cbor_value_get_int64_checked(it, &i64) == CborNoError) { + cbor_value_get_int64(it, &i64_unchecked); + CHECK(i64 == i64_unchecked); + CHECK(cbor_value_is_negative_integer(it) ? i64 < 0 : i64 >= 0); + } + if (cbor_value_get_int_checked(it, &i) == CborNoError) { + cbor_value_get_int(it, &i_unchecked); + CHECK(i == i_unchecked); + } +} + +static void parse_floating_point(const CborValue *it) +{ + float f; + double d; + uint16_t half; + + switch (cbor_value_get_type(it)) { + case CborHalfFloatType: + cbor_value_get_half_float(it, &half); + cbor_value_get_half_float_as_float(it, &f); + sink += half; + /* NaN in half-precision is NaN in single-precision */ + CHECK(((half & 0x7c00) == 0x7c00 && (half & 0x3ff)) == (f != f)); + break; + case CborFloatType: + cbor_value_get_float(it, &f); + memcpy(&half, &f, sizeof(half)); + sink += half; + break; + case CborDoubleType: + cbor_value_get_double(it, &d); + memcpy(&half, &d, sizeof(half)); + sink += half; + break; + default: + break; + } +} + +/* Reads a string with every method and cross-checks them. On success, *it + * points to the next item. */ +static CborError parse_string(CborValue *it) +{ + CborError err; + CborValue chunks = *it; + CborValue next; + size_t len, total, n; + uint8_t *buffer; + uint8_t *copy; + const void *ptr; + bool equals; + bool text = cbor_value_is_text_string(it); + + if (cbor_value_is_length_known(it)) { + err = cbor_value_get_string_length(it, &len); + if (err) + return err; + } + + err = cbor_value_calculate_string_length(it, &len); + if (err) + return err; + + if (text) + err = cbor_value_dup_text_string(it, (char **)&buffer, &n, &next); + else + err = cbor_value_dup_byte_string(it, &buffer, &n, &next); + if (err) + return err; + CHECK(n == len); + sink += checksum(buffer, len); + + /* copy into a buffer without room for the NUL and into one that is one + * byte too small */ + copy = (uint8_t *)malloc(len ? len : 1); + CHECK(copy); + n = len; + CHECK(copy_string(it, copy, &n, NULL) == CborNoError); + CHECK(n == len && memcmp(copy, buffer, len) == 0); + if (len) { + n = len - 1; + CHECK(copy_string(it, copy, &n, NULL) == CborErrorOutOfMemory); + } + free(copy); + + /* iterate over the chunks and compare them to the dup'ed string */ + err = cbor_value_begin_string_iteration(&chunks); + total = 0; + while (!err) { + err = get_string_chunk(&chunks, &ptr, &n); + if (err == CborErrorNoMoreStringChunks) { + err = cbor_value_finish_string_iteration(&chunks); + break; + } + if (!err) { + CHECK(n <= len - total); + CHECK(memcmp(buffer + total, ptr, n) == 0); + total += n; + } + } + CHECK(err == CborNoError); + CHECK(total == len); + CHECK(cbor_value_get_next_byte(&chunks) == cbor_value_get_next_byte(&next)); + + if (text && memchr(buffer, '\0', len) == NULL) { + CHECK(cbor_value_text_string_equals(it, (const char *)buffer, &equals) == CborNoError); + CHECK(equals); + if (len) { + buffer[len - 1] = '\0'; + CHECK(cbor_value_text_string_equals(it, (const char *)buffer, &equals) == CborNoError); + CHECK(!equals); + } + } + + free(buffer); + *it = next; + return CborNoError; +} + +/* Reads a string when using the reader API: the source can't be rewound, so + * the string must be read exactly once. */ +static CborError parse_string_reader(struct Context *ctx, CborValue *it) +{ + CborError err; + const void *ptr; + size_t n; + size_t len = 0; + size_t total = 0; + bool length_known = cbor_value_is_length_known(it); + + if (length_known) { + err = cbor_value_get_string_length(it, &len); + if (err) + return err; + } + + if (ctx->reader_advance) { + /* the buffer is as large as the whole input, so it's big enough */ + n = ctx->buffer_size; + err = copy_string(it, ctx->buffer, &n, it); + if (err) + return err; + CHECK(!length_known || n == len); + sink += checksum(ctx->buffer, n); + return CborNoError; + } + + err = cbor_value_begin_string_iteration(it); + while (!err) { + err = get_string_chunk(it, &ptr, &n); + if (err == CborErrorNoMoreStringChunks) { + CHECK(!length_known || total == len); + return cbor_value_finish_string_iteration(it); + } + if (!err) { + sink += checksum(ptr, n); + total += n; + } + } + return err; +} + +static CborError parse_container(struct Context *ctx, CborValue *it, int nesting) +{ + CborError err; + CborValue recursed; + CborValue element; + size_t len; + + if (nesting == 0) + return CborErrorNestingTooDeep; + + if (cbor_value_is_length_known(it)) { + if (cbor_value_is_array(it)) + err = cbor_value_get_array_length(it, &len); + else + err = cbor_value_get_map_length(it, &len); + if (err) + return err; + } + + if (ctx->reader_advance) + return cbor_value_advance(it); + + if (!ctx->reader && cbor_value_is_map(it) && expensive_check(ctx)) { + /* the result is irrelevant, we only need the search to run */ + cbor_value_map_find_value(it, "a", &element); + } + + err = cbor_value_enter_container(it, &recursed); + if (err) + return err; + while (!cbor_value_at_end(&recursed)) { + err = parse_value(ctx, &recursed, nesting - 1); + if (err) + return err; + } + return cbor_value_leave_container(it, &recursed); +} + +/* Decodes the item at *it and advances past it */ +static CborError parse_value(struct Context *ctx, CborValue *it, int nesting) +{ + CborValue skipped; + CborTag tag; + uint8_t simple; + bool boolean; + + switch (cbor_value_get_type(it)) { + case CborIntegerType: + parse_integer(it); + return cbor_value_advance_fixed(it); + + case CborByteStringType: + case CborTextStringType: + return ctx->reader ? parse_string_reader(ctx, it) : parse_string(it); + + case CborArrayType: + case CborMapType: + return parse_container(ctx, it, nesting); + + case CborTagType: + cbor_value_get_tag(it, &tag); + sink += tag; + if (!ctx->reader && expensive_check(ctx)) { + skipped = *it; + if (cbor_value_skip_tag(&skipped) == CborNoError) + CHECK(!cbor_value_is_tag(&skipped)); + /* this skips the tags too */ + cbor_value_text_string_equals(it, "", &boolean); + } + /* the tagged item is visited by the caller as the next item */ + return cbor_value_advance_fixed(it); + + case CborSimpleType: + cbor_value_get_simple_type(it, &simple); + sink += simple; + return cbor_value_advance_fixed(it); + + case CborBooleanType: + cbor_value_get_boolean(it, &boolean); + sink += boolean; + return cbor_value_advance_fixed(it); + + case CborNullType: + case CborUndefinedType: + return cbor_value_advance_fixed(it); + + case CborHalfFloatType: + case CborFloatType: + case CborDoubleType: + parse_floating_point(it); + return cbor_value_advance_fixed(it); + + case CborInvalidType: + default: + /* preparsing never produces an invalid iterator without an error */ + abort(); + } +} + +static void parse_reader(struct Context *ctx, const uint8_t *data, size_t size, uint32_t config) +{ + struct ReaderInput input = { data, size, 0 }; + CborParser parser; + CborValue it; + CborError err; + + ctx->buffer_size = size + 1; + ctx->buffer = (uint8_t *)malloc(ctx->buffer_size); + CHECK(ctx->buffer); + + if (config & ConfigIncremental) + input.size = 0; + + while (input.consumed < size) { + size_t consumed = input.consumed; + memset(&it, 0, sizeof(it)); + err = cbor_parser_init_reader(&reader_ops, &parser, &it, &input); + while (err == CborErrorUnexpectedEOF && input.size < size) { + /* make one more byte available and try again */ + CHECK(input.consumed == consumed); + ++input.size; + err = cbor_value_reparse(&it); + } + input.size = size; + + while (!err && !cbor_value_at_end(&it)) + err = parse_value(ctx, &it, MAX_NESTING); + if (err || input.consumed == consumed) + break; + } + free(ctx->buffer); +} + +static void parse_buffer(struct Context *ctx, const uint8_t *data, size_t size) +{ + const uint8_t *ptr = data; + const uint8_t *end = data + size; + CborParser parser; + CborValue it; + CborValue advanced; + CborError err; + CborError advanced_err; + + /* the input is a sequence of items (RFC 8742) */ + while (ptr < end) { + err = cbor_parser_init(ptr, (size_t)(end - ptr), 0, &parser, &it); + while (!err && !cbor_value_at_end(&it)) { + /* reference result to compare with the item-by-item traversal */ + advanced = it; + advanced_err = cbor_value_advance(&advanced); + err = parse_value(ctx, &it, MAX_NESTING); + if (!err && !advanced_err) + CHECK(cbor_value_get_next_byte(&it) == cbor_value_get_next_byte(&advanced)); + } + if (err) + break; + CHECK(cbor_value_get_next_byte(&it) > ptr && cbor_value_get_next_byte(&it) <= end); + ptr = cbor_value_get_next_byte(&it); + } +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct Context ctx; + uint32_t config; + + if (size < sizeof(config)) + return 0; + memcpy(&config, data, sizeof(config)); + data += sizeof(config); + size -= sizeof(config); + + memset(&ctx, 0, sizeof(ctx)); + ctx.expensive_checks = MAX_EXPENSIVE_CHECKS; + if (config & ConfigUseReader) { + ctx.reader = true; + ctx.reader_advance = (config & ConfigReaderAdvance) != 0; + parse_reader(&ctx, data, size, config); + } else { + parse_buffer(&ctx, data, size); + } + return 0; +} diff --git a/fuzz/pretty_fuzzer.c b/fuzz/pretty_fuzzer.c new file mode 100644 index 00000000..92e7502b --- /dev/null +++ b/fuzz/pretty_fuzzer.c @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2026 Topogamer0 +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +/* + * Fuzzes the conversion of CBOR to diagnostic notation, both with + * cbor_value_to_pretty_advance_flags() (writing to a FILE *) and with + * cbor_value_to_pretty_stream() (writing through a callback). + * + * The first 4 bytes of the input are a configuration word whose low bits are + * the CborPrettyFlags to use (see FuzzConfig); the rest is the CBOR payload, + * which is converted as a sequence of items. The callback can be made to fail + * after a number of calls, to exercise the error handling. + */ + +#include "cbor.h" + +#include +#include +#include +#include + +#ifdef NDEBUG +# error "The fuzzers must be built without NDEBUG: TinyCBOR's assertions check the API usage" +#endif + +enum FuzzConfig { + PrettyFlagsMask = CborPrettyNumericEncodingIndicators | CborPrettyIndicateIndeterminateLength | + CborPrettyIndicateOverlongNumbers | CborPrettyShowStringFragments, + + /* if not zero, the callback fails on that call (bits 16 to 23) */ + ConfigFailShift = 16, + ConfigFailMask = 0xff, + + /* use cbor_value_to_pretty_stream() instead of a FILE * */ + ConfigUseStream = 0x80000000U +}; + +struct Output +{ + char buffer[256]; + size_t total; + unsigned calls_until_failure; +}; + +static CborError stream_function(void *token, const char *fmt, ...) +{ + struct Output *output = (struct Output *)token; + va_list ap; + int n; + + if (output->calls_until_failure && --output->calls_until_failure == 0) + return CborErrorIO; + + va_start(ap, fmt); + n = vsnprintf(output->buffer, sizeof(output->buffer), fmt, ap); + va_end(ap); + if (n < 0) + return CborErrorIO; + output->total += (size_t)n; + return CborNoError; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + static FILE *out; + struct Output output = { { 0 }, 0, 0 }; + CborParser parser; + CborValue it; + CborError err; + uint32_t config; + int flags; + const uint8_t *ptr; + const uint8_t *end; + + if (!out) + out = fopen("/dev/null", "w"); + if (!out || size < sizeof(config)) + return 0; + memcpy(&config, data, sizeof(config)); + data += sizeof(config); + size -= sizeof(config); + end = data + size; + flags = (int)(config & PrettyFlagsMask); + output.calls_until_failure = (config >> ConfigFailShift) & ConfigFailMask; + + ptr = data; + while (ptr < end) { + err = cbor_parser_init(ptr, (size_t)(end - ptr), 0, &parser, &it); + if (!err) { + if (config & ConfigUseStream) + err = cbor_value_to_pretty_stream(stream_function, &output, &it, flags); + else + err = cbor_value_to_pretty_advance_flags(out, &it, flags); + } + if (err || cbor_value_get_next_byte(&it) <= ptr) + break; + ptr = cbor_value_get_next_byte(&it); + } + return 0; +} diff --git a/fuzz/tojson_fuzzer.c b/fuzz/tojson_fuzzer.c new file mode 100644 index 00000000..a371fb2d --- /dev/null +++ b/fuzz/tojson_fuzzer.c @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2026 Topogamer0 +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +/* + * Fuzzes the conversion of CBOR to JSON with cbor_value_to_json_advance(). + * + * The first 4 bytes of the input are a configuration word whose low bits are + * the CborToJsonFlags to use; the rest is the CBOR payload, which is + * converted as a sequence of items. Where available (glibc), the output + * stream can be made to fail after a number of bytes, to exercise the error + * handling. + */ + +#define _GNU_SOURCE 1 /* for fopencookie() */ + +#include "cbor.h" +#include "cborjson.h" + +#include +#include +#include + +#ifdef NDEBUG +# error "The fuzzers must be built without NDEBUG: TinyCBOR's assertions check the API usage" +#endif + +enum FuzzConfig { + JsonFlagsMask = CborConvertAddMetadata | CborConvertTagsToObjects | + CborConvertByteStringsToBase64Url | CborConvertStringifyMapKeys, + + /* if not zero, writing fails after this many bytes (bits 16 to 31) */ + ConfigFailShift = 16 +}; + +#ifdef __GLIBC__ +static ssize_t failing_write(void *cookie, const char *buf, size_t size) +{ + size_t *bytes_until_failure = (size_t *)cookie; + (void)buf; + if (size > *bytes_until_failure) { + *bytes_until_failure = 0; + return -1; + } + *bytes_until_failure -= size; + return (ssize_t)size; +} + +static FILE *open_failing_stream(size_t *bytes_until_failure) +{ + cookie_io_functions_t functions = { NULL, failing_write, NULL, NULL }; + FILE *f = fopencookie(bytes_until_failure, "w", functions); + if (f) + setvbuf(f, NULL, _IONBF, 0); /* fail as soon as possible */ + return f; +} +#endif + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + static FILE *devnull; + FILE *out; + CborParser parser; + CborValue it; + CborError err; + uint32_t config; + size_t bytes_until_failure; + const uint8_t *ptr; + const uint8_t *end; + + if (!devnull) + devnull = fopen("/dev/null", "w"); + if (!devnull || size < sizeof(config)) + return 0; + memcpy(&config, data, sizeof(config)); + data += sizeof(config); + size -= sizeof(config); + end = data + size; + + out = devnull; + bytes_until_failure = config >> ConfigFailShift; +#ifdef __GLIBC__ + if (bytes_until_failure) { + out = open_failing_stream(&bytes_until_failure); + if (!out) + return 0; + } +#endif + + ptr = data; + while (ptr < end) { + err = cbor_parser_init(ptr, (size_t)(end - ptr), 0, &parser, &it); + if (!err) + err = cbor_value_to_json_advance(out, &it, (int)(config & JsonFlagsMask)); + if (err || cbor_value_get_next_byte(&it) <= ptr) + break; + ptr = cbor_value_get_next_byte(&it); + } + + if (out != devnull) + fclose(out); + return 0; +} diff --git a/fuzz/validate_fuzzer.c b/fuzz/validate_fuzzer.c new file mode 100644 index 00000000..0241afda --- /dev/null +++ b/fuzz/validate_fuzzer.c @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2026 Topogamer0 +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +/* + * Fuzzes cbor_value_validate() with every combination of validation flags. + * + * The first 4 bytes of the input are the CborValidationFlags to use; the rest + * is the CBOR payload. + */ + +#include "cbor.h" + +#include +#include +#include + +#ifdef NDEBUG +# error "The fuzzers must be built without NDEBUG: TinyCBOR's assertions check the API usage" +#endif + +/* Abort on a result that contradicts the documented behavior */ +#define CHECK(cond) do { if (!(cond)) abort(); } while (0) + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + CborParser parser; + CborValue it; + CborValue copy; + CborError err; + CborError basic_err; + uint32_t flags; + + if (size < sizeof(flags)) + return 0; + memcpy(&flags, data, sizeof(flags)); + data += sizeof(flags); + size -= sizeof(flags); + + if (cbor_parser_init(data, size, 0, &parser, &it) != CborNoError) + return 0; + + err = cbor_value_validate(&it, flags); + basic_err = cbor_value_validate_basic(&it); + + /* "If flags is CborValidateBasic, the result should be the same as + * cbor_value_validate_basic()". That one advances over a tag without + * looking at the tagged item, so only compare for other types. The two + * also count nesting differently towards CBOR_PARSER_MAX_RECURSIONS. */ + if (flags == CborValidateBasic && !cbor_value_is_tag(&it) && + err != CborErrorNestingTooDeep && basic_err != CborErrorNestingTooDeep) + CHECK((err == CborNoError) == (basic_err == CborNoError)); + + /* "If no error was found, it returns CborNoError and the application can + * iterate over the items with certainty that no errors will appear + * during parsing" */ + if (err == CborNoError) { + CHECK(basic_err == CborNoError); + /* cbor_value_advance() over a tag stops at the tagged item */ + copy = it; + CHECK(cbor_value_skip_tag(©) == CborNoError); + CHECK(cbor_value_advance(©) == CborNoError); + if (flags & CborValidateCompleteData) + CHECK(cbor_value_get_next_byte(©) == data + size); + } + return 0; +}