1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_ipc_ProtocolFuzzer_h
8 #define mozilla_ipc_ProtocolFuzzer_h
9 
10 #include "chrome/common/ipc_message.h"
11 
12 #include "mozilla/RefPtr.h"
13 #include "mozilla/UniquePtrExtensions.h"
14 #include "mozilla/dom/ContentParent.h"
15 
16 namespace mozilla {
17 namespace ipc {
18 
19 class ProtocolFuzzerHelper {
20  public:
21   static mozilla::dom::ContentParent* CreateContentParent(
22       const nsACString& aRemoteType);
23 
24   static void CompositorBridgeParentSetup();
25 
AddShmemToProtocol(IToplevelProtocol * aProtocol,Shmem::SharedMemory * aSegment,int32_t aId)26   static void AddShmemToProtocol(IToplevelProtocol* aProtocol,
27                                  Shmem::SharedMemory* aSegment, int32_t aId) {
28     MOZ_ASSERT(!aProtocol->mShmemMap.Contains(aId),
29                "Don't insert with an existing ID");
30     aProtocol->mShmemMap.InsertOrUpdate(aId, aSegment);
31   }
32 
RemoveShmemFromProtocol(IToplevelProtocol * aProtocol,int32_t aId)33   static void RemoveShmemFromProtocol(IToplevelProtocol* aProtocol,
34                                       int32_t aId) {
35     aProtocol->mShmemMap.Remove(aId);
36   }
37 };
38 
39 template <typename T>
FuzzProtocol(T * aProtocol,const uint8_t * aData,size_t aSize,const nsTArray<nsCString> & aIgnoredMessageTypes)40 void FuzzProtocol(T* aProtocol, const uint8_t* aData, size_t aSize,
41                   const nsTArray<nsCString>& aIgnoredMessageTypes) {
42   while (true) {
43     uint32_t msg_size =
44         IPC::Message::MessageSize(reinterpret_cast<const char*>(aData),
45                                   reinterpret_cast<const char*>(aData) + aSize);
46     if (msg_size == 0 || msg_size > aSize) {
47       break;
48     }
49     IPC::Message m(reinterpret_cast<const char*>(aData), msg_size);
50     aSize -= msg_size;
51     aData += msg_size;
52 
53     // We ignore certain message types
54     if (aIgnoredMessageTypes.Contains(m.name())) {
55       continue;
56     }
57 
58     uint8_t num_shmems = 0;
59     if (aSize) {
60       num_shmems = *aData;
61       aData++;
62       aSize--;
63 
64       for (uint32_t i = 0; i < num_shmems; i++) {
65         if (aSize < sizeof(uint16_t)) {
66           break;
67         }
68         size_t shmem_size = *reinterpret_cast<const uint16_t*>(aData);
69         aData += sizeof(uint16_t);
70         aSize -= sizeof(uint16_t);
71 
72         if (shmem_size > aSize) {
73           break;
74         }
75         RefPtr<Shmem::SharedMemory> segment(
76             Shmem::Alloc(Shmem::PrivateIPDLCaller(), shmem_size,
77                          SharedMemory::TYPE_BASIC, false));
78         if (!segment) {
79           break;
80         }
81 
82         Shmem shmem(Shmem::PrivateIPDLCaller(), segment.get(), i + 1);
83         memcpy(shmem.get<uint8_t>(), aData, shmem_size);
84         ProtocolFuzzerHelper::AddShmemToProtocol(
85             aProtocol, segment.forget().take(), i + 1);
86 
87         aData += shmem_size;
88         aSize -= shmem_size;
89       }
90     }
91     // TODO: attach |m.header().num_fds| file descriptors to |m|. MVP can be
92     // empty files, next implementation maybe read a length header from |data|
93     // and then that many bytes.
94 
95     if (m.is_sync()) {
96       UniquePtr<IPC::Message> reply;
97       aProtocol->OnMessageReceived(m, *getter_Transfers(reply));
98     } else {
99       aProtocol->OnMessageReceived(m);
100     }
101     for (uint32_t i = 0; i < num_shmems; i++) {
102       Shmem::SharedMemory* segment = aProtocol->LookupSharedMemory(i + 1);
103       Shmem::Dealloc(Shmem::PrivateIPDLCaller(), segment);
104       ProtocolFuzzerHelper::RemoveShmemFromProtocol(aProtocol, i + 1);
105     }
106   }
107 }
108 
109 nsTArray<nsCString> LoadIPCMessageBlacklist(const char* aPath);
110 
111 }  // namespace ipc
112 }  // namespace mozilla
113 
114 #endif
115