#include #include #include #include #include #include #include namespace fs = std::filesystem; namespace { constexpr size_t kMaxConfigBytes = 2048; std::vector pluginCandidates() { std::vector out; const fs::path base = "/src/build/fuzzing/tools/fuzzing"; const fs::path test1 = base / "libfuzz_abi_test_plugin.so"; const fs::path test2 = base / "libfuzz_abi_negotiation_plugin.so"; if (fs::exists(test1)) out.push_back(test1); if (fs::exists(test2)) out.push_back(test2); return out; } std::string configFromBytes(const uint8_t* data, size_t size) { if (!data || size == 0) return "{}"; const size_t n = std::min(size, kMaxConfigBytes); std::string payload(reinterpret_cast(data), n); for (char& c : payload) { unsigned char uc = static_cast(c); if (uc < 0x20 || uc == '"' || uc == '\\') { c = '_'; } } return std::string("{\"neg\":\"") + payload + "\"}"; } } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (!data || size == 0) return 0; static const bool envInit = [] { setenv("YAMS_PLUGIN_TRUST_ALL", "1", 1); return true; }(); (void)envInit; auto plugins = pluginCandidates(); if (plugins.empty()) { return 0; } const fs::path pluginRoot = plugins.front().parent_path(); yams::daemon::AbiPluginLoader loader; loader.setNamePolicy((data[0] & 1) ? yams::daemon::AbiPluginLoader::NamePolicy::Spec : yams::daemon::AbiPluginLoader::NamePolicy::Relaxed); (void)loader.scanDirectory(pluginRoot); std::string configJson = configFromBytes(data, size); size_t start = static_cast(data[0]) % plugins.size(); for (size_t i = 0; i < plugins.size(); ++i) { const fs::path& p = plugins[(start + i) % plugins.size()]; auto loaded = loader.load(p, configJson); if (!loaded) { continue; } const auto& info = loaded.value(); (void)loader.health(info.name); for (const auto& iface : info.interfaces) { uint32_t v = 1u + static_cast(data[(i + iface.size()) % size] % 3u); (void)loader.getInterface(info.name, iface, v); } std::string dynId = "iface_"; dynId += static_cast('a' + (data[i % size] % 26)); (void)loader.getInterface(info.name, dynId, static_cast(data[(i + 1) % size])); (void)loader.unload(info.name); } return 0; }