| /* |
| * Copyright (c) 2022 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "AppMain.h" |
| #include <app/codegen-data-model-provider/Instance.h> |
| #include <app/server/Server.h> |
| |
| #include <CommissionableInit.h> |
| |
| using namespace chip; |
| using namespace chip::DeviceLayer; |
| |
| namespace { |
| |
| LinuxCommissionableDataProvider gCommissionableDataProvider; |
| |
| } |
| |
| void CleanShutdown() |
| { |
| ApplicationShutdown(); |
| Server::GetInstance().Shutdown(); |
| PlatformMgr().Shutdown(); |
| // TODO: We don't Platform::MemoryShutdown because ~CASESessionManager calls |
| // Dnssd::ResolverProxy::Shutdown, which starts doing Platform::Delete. |
| // Platform::MemoryShutdown(); |
| } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t * aData, size_t aSize) |
| { |
| static bool matterStackInitialized = false; |
| if (!matterStackInitialized) |
| { |
| // Might be simpler to do ChipLinuxAppInit() with argc == 0, argv set to |
| // just a fake executable name? |
| VerifyOrDie(Platform::MemoryInit() == CHIP_NO_ERROR); |
| VerifyOrDie(PlatformMgr().InitChipStack() == CHIP_NO_ERROR); |
| |
| VerifyOrDie(chip::examples::InitCommissionableDataProvider(gCommissionableDataProvider, |
| LinuxDeviceOptions::GetInstance()) == CHIP_NO_ERROR); |
| SetCommissionableDataProvider(&gCommissionableDataProvider); |
| |
| // ChipLinuxAppMainLoop blocks, and we don't want that here. |
| static chip::CommonCaseDeviceServerInitParams initParams; |
| (void) initParams.InitializeStaticResourcesBeforeServerInit(); |
| initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); |
| VerifyOrDie(Server::GetInstance().Init(initParams) == CHIP_NO_ERROR); |
| |
| ApplicationInit(); |
| |
| // We don't start the event loop task, because we don't plan to deliver |
| // data on a separate thread. |
| |
| matterStackInitialized = true; |
| |
| // The fuzzer does not have a way to tell us when it's done, so just |
| // shut down things on exit. |
| atexit(CleanShutdown); |
| } |
| |
| // For now, just dump the data as a UDP payload into the session manager. |
| // But maybe we should try to separately extract a PeerAddress and data from |
| // the incoming data? |
| |
| // To avoid out-of-bounds access when acessing aData[1] |
| if (aSize < 2) |
| { |
| return 0; |
| } |
| |
| // dumping payload with fuzzed transport types |
| constexpr uint8_t numberOfTypes = static_cast<int>(Transport::Type::kLast) + 1; |
| Transport::Type fuzzedTransportType = static_cast<Transport::Type>(aData[0] % numberOfTypes); |
| Transport::PeerAddress peerAddr(fuzzedTransportType); |
| |
| System::PacketBufferHandle buf = |
| System::PacketBufferHandle::NewWithData(&aData[1], aSize - 1, /* aAdditionalSize = */ 0, /* aReservedSize = */ 0); |
| if (buf.IsNull()) |
| { |
| // Too big; we couldn't represent this as a packetbuffer to start with. |
| return 0; |
| } |
| |
| // Ignoring the return value from OnMessageReceived, because we might be |
| // passing it all sorts of garbage that will cause it to fail. |
| |
| // for TCP we need to have MessageTransportContext |
| if (fuzzedTransportType == Transport::Type::kTcp) |
| { |
| Transport::MessageTransportContext msgContext; |
| Server::GetInstance().GetSecureSessionManager().OnMessageReceived(peerAddr, std::move(buf), &msgContext); |
| } |
| else |
| { |
| Server::GetInstance().GetSecureSessionManager().OnMessageReceived(peerAddr, std::move(buf)); |
| } |
| // Now process pending events until our sentinel is reached. |
| PlatformMgr().ScheduleWork([](intptr_t) { PlatformMgr().StopEventLoopTask(); }); |
| PlatformMgr().RunEventLoop(); |
| return 0; |
| } |