/work/obj-fuzz/dist/include/ProtocolFuzzer.h
Line | Count | Source (jump to first uncovered line) |
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/dom/ContentParent.h" |
14 | | |
15 | | namespace mozilla { |
16 | | namespace ipc { |
17 | | |
18 | | class ProtocolFuzzerHelper |
19 | | { |
20 | | public: |
21 | | static mozilla::dom::ContentParent* CreateContentParent( |
22 | | mozilla::dom::ContentParent* aOpener, |
23 | | const nsAString& aRemoteType); |
24 | | |
25 | | template<typename T> |
26 | | static void AddShmemToProtocol(T* aProtocol, |
27 | | Shmem::SharedMemory* aSegment, |
28 | | int32_t aId) |
29 | 0 | { |
30 | 0 | GetToplevelState(aProtocol)->mShmemMap.AddWithID(aSegment, aId); |
31 | 0 | } |
32 | | |
33 | | template<typename T> |
34 | | static void RemoveShmemFromProtocol(T* aProtocol, int32_t aId) |
35 | 0 | { |
36 | 0 | GetToplevelState(aProtocol)->mShmemMap.RemoveIfPresent(aId); |
37 | 0 | } |
38 | | |
39 | | private: |
40 | | template<typename T> |
41 | | static mozilla::ipc::IToplevelProtocol::ToplevelState* GetToplevelState( |
42 | | T* aProtocol) |
43 | 0 | { |
44 | 0 | static_assert(std::is_base_of<mozilla::ipc::IToplevelProtocol, T>::value, |
45 | 0 | "Only ToplevelProtocols are supported for now"); |
46 | 0 | return static_cast<mozilla::ipc::IToplevelProtocol::ToplevelState*>( |
47 | 0 | static_cast<mozilla::ipc::IToplevelProtocol*>(aProtocol)->mState.get()); |
48 | 0 | } |
49 | | }; |
50 | | |
51 | | template<typename T> |
52 | | void |
53 | | FuzzProtocol(T* aProtocol, |
54 | | const uint8_t* aData, |
55 | | size_t aSize, |
56 | | const nsTArray<nsCString>& aIgnoredMessageTypes) |
57 | 0 | { |
58 | 0 | while (true) { |
59 | 0 | uint32_t msg_size = |
60 | 0 | IPC::Message::MessageSize(reinterpret_cast<const char*>(aData), |
61 | 0 | reinterpret_cast<const char*>(aData) + aSize); |
62 | 0 | if (msg_size == 0 || msg_size > aSize) { |
63 | 0 | break; |
64 | 0 | } |
65 | 0 | IPC::Message m(reinterpret_cast<const char*>(aData), msg_size); |
66 | 0 | aSize -= msg_size; |
67 | 0 | aData += msg_size; |
68 | 0 |
|
69 | 0 | // We ignore certain message types |
70 | 0 | if (aIgnoredMessageTypes.Contains(m.name())) { |
71 | 0 | continue; |
72 | 0 | } |
73 | 0 | |
74 | 0 | uint8_t num_shmems = 0; |
75 | 0 | if (aSize) { |
76 | 0 | num_shmems = *aData; |
77 | 0 | aData++; |
78 | 0 | aSize--; |
79 | 0 |
|
80 | 0 | for (uint32_t i = 0; i < num_shmems; i++) { |
81 | 0 | if (aSize < sizeof(uint16_t)) { |
82 | 0 | break; |
83 | 0 | } |
84 | 0 | size_t shmem_size = *reinterpret_cast<const uint16_t*>(aData); |
85 | 0 | aData += sizeof(uint16_t); |
86 | 0 | aSize -= sizeof(uint16_t); |
87 | 0 |
|
88 | 0 | if (shmem_size > aSize) { |
89 | 0 | break; |
90 | 0 | } |
91 | 0 | RefPtr<Shmem::SharedMemory> segment( |
92 | 0 | Shmem::Alloc(Shmem::PrivateIPDLCaller(), |
93 | 0 | shmem_size, |
94 | 0 | SharedMemory::TYPE_BASIC, |
95 | 0 | false)); |
96 | 0 | if (!segment) { |
97 | 0 | break; |
98 | 0 | } |
99 | 0 | |
100 | 0 | Shmem shmem(Shmem::PrivateIPDLCaller(), segment.get(), i + 1); |
101 | 0 | memcpy(shmem.get<uint8_t>(), aData, shmem_size); |
102 | 0 | ProtocolFuzzerHelper::AddShmemToProtocol( |
103 | 0 | aProtocol, segment.forget().take(), i + 1); |
104 | 0 |
|
105 | 0 | aData += shmem_size; |
106 | 0 | aSize -= shmem_size; |
107 | 0 | } |
108 | 0 | } |
109 | 0 | // TODO: attach |m.header().num_fds| file descriptors to |m|. MVP can be |
110 | 0 | // empty files, next implementation maybe read a length header from |data| |
111 | 0 | // and then that many bytes. |
112 | 0 |
|
113 | 0 | if (m.is_sync()) { |
114 | 0 | nsAutoPtr<IPC::Message> reply; |
115 | 0 | aProtocol->OnMessageReceived(m, *getter_Transfers(reply)); |
116 | 0 | } else { |
117 | 0 | aProtocol->OnMessageReceived(m); |
118 | 0 | } |
119 | 0 | for (uint32_t i = 0; i < num_shmems; i++) { |
120 | 0 | Shmem::SharedMemory* segment = aProtocol->LookupSharedMemory(i + 1); |
121 | 0 | Shmem::Dealloc(Shmem::PrivateIPDLCaller(), segment); |
122 | 0 | ProtocolFuzzerHelper::RemoveShmemFromProtocol(aProtocol, i + 1); |
123 | 0 | } |
124 | 0 | } |
125 | 0 | } |
126 | | |
127 | | nsTArray<nsCString> LoadIPCMessageBlacklist(const char* aPath); |
128 | | |
129 | | } |
130 | | } |
131 | | |
132 | | #endif |