PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/crashpad/crashpad/util/ios/ios_intermediate_dump_reader_test.cc

https://github.com/chromium/chromium
C++ | 265 lines | 207 code | 40 blank | 18 comment | 1 complexity | a140369ce71d2f068fbdc801b02443f5 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, Apache-2.0, BSD-3-Clause
  1. // Copyright 2021 The Crashpad Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "util/ios/ios_intermediate_dump_reader.h"
  15. #include <fcntl.h>
  16. #include <mach/vm_map.h>
  17. #include "base/posix/eintr_wrapper.h"
  18. #include "gmock/gmock.h"
  19. #include "gtest/gtest.h"
  20. #include "test/errors.h"
  21. #include "test/scoped_temp_dir.h"
  22. #include "util/file/filesystem.h"
  23. #include "util/ios/ios_intermediate_dump_data.h"
  24. #include "util/ios/ios_intermediate_dump_format.h"
  25. #include "util/ios/ios_intermediate_dump_list.h"
  26. #include "util/ios/ios_intermediate_dump_writer.h"
  27. namespace crashpad {
  28. namespace test {
  29. namespace {
  30. using Key = internal::IntermediateDumpKey;
  31. using Result = internal::IOSIntermediateDumpReaderInitializeResult;
  32. using internal::IOSIntermediateDumpWriter;
  33. class IOSIntermediateDumpReaderTest : public testing::Test {
  34. protected:
  35. // testing::Test:
  36. void SetUp() override {
  37. path_ = temp_dir_.path().Append("dump_file");
  38. fd_ = base::ScopedFD(HANDLE_EINTR(
  39. ::open(path_.value().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644)));
  40. ASSERT_GE(fd_.get(), 0) << ErrnoMessage("open");
  41. writer_ = std::make_unique<IOSIntermediateDumpWriter>();
  42. ASSERT_TRUE(writer_->Open(path_));
  43. ASSERT_TRUE(IsRegularFile(path_));
  44. dump_interface_.Initialize(path_);
  45. }
  46. void TearDown() override {
  47. ASSERT_TRUE(writer_->Close());
  48. fd_.reset();
  49. writer_.reset();
  50. EXPECT_FALSE(IsRegularFile(path_));
  51. }
  52. int fd() { return fd_.get(); }
  53. const base::FilePath& path() const { return path_; }
  54. const auto& dump_interface() const { return dump_interface_; }
  55. std::unique_ptr<IOSIntermediateDumpWriter> writer_;
  56. private:
  57. base::ScopedFD fd_;
  58. ScopedTempDir temp_dir_;
  59. base::FilePath path_;
  60. internal::IOSIntermediateDumpFilePath dump_interface_;
  61. };
  62. TEST_F(IOSIntermediateDumpReaderTest, ReadNoFile) {
  63. internal::IOSIntermediateDumpReader reader;
  64. internal::IOSIntermediateDumpFilePath dump_interface;
  65. EXPECT_FALSE(dump_interface.Initialize(base::FilePath()));
  66. EXPECT_FALSE(IsRegularFile(path()));
  67. }
  68. TEST_F(IOSIntermediateDumpReaderTest, ReadEmptyFile) {
  69. internal::IOSIntermediateDumpReader reader;
  70. EXPECT_EQ(reader.Initialize(dump_interface()), Result::kFailure);
  71. EXPECT_FALSE(IsRegularFile(path()));
  72. }
  73. TEST_F(IOSIntermediateDumpReaderTest, ReadHelloWorld) {
  74. std::string hello_world("hello world.");
  75. EXPECT_TRUE(
  76. LoggingWriteFile(fd(), hello_world.c_str(), hello_world.length()));
  77. internal::IOSIntermediateDumpReader reader;
  78. EXPECT_EQ(reader.Initialize(dump_interface()), Result::kIncomplete);
  79. EXPECT_FALSE(IsRegularFile(path()));
  80. const auto root_map = reader.RootMap();
  81. EXPECT_TRUE(root_map->empty());
  82. }
  83. TEST_F(IOSIntermediateDumpReaderTest, FuzzTestCases) {
  84. constexpr uint8_t fuzz1[] = {0x6,
  85. 0x5,
  86. 0x0,
  87. 0xff,
  88. 0xff,
  89. 0xfd,
  90. 0x1,
  91. 0xff,
  92. 0xff,
  93. 0xff,
  94. 0xff,
  95. 0xff,
  96. 0xfd,
  97. 0x1,
  98. 0x7,
  99. 0x16};
  100. internal::IOSIntermediateDumpByteArray dump_interface(fuzz1, sizeof(fuzz1));
  101. internal::IOSIntermediateDumpReader reader;
  102. EXPECT_EQ(reader.Initialize(dump_interface), Result::kIncomplete);
  103. const auto root_map = reader.RootMap();
  104. EXPECT_TRUE(root_map->empty());
  105. }
  106. TEST_F(IOSIntermediateDumpReaderTest, WriteBadPropertyDataLength) {
  107. internal::IOSIntermediateDumpReader reader;
  108. IOSIntermediateDumpWriter::CommandType command_type =
  109. IOSIntermediateDumpWriter::CommandType::kRootMapStart;
  110. EXPECT_TRUE(LoggingWriteFile(fd(), &command_type, sizeof(command_type)));
  111. command_type = IOSIntermediateDumpWriter::CommandType::kProperty;
  112. EXPECT_TRUE(LoggingWriteFile(fd(), &command_type, sizeof(command_type)));
  113. Key key = Key::kVersion;
  114. EXPECT_TRUE(LoggingWriteFile(fd(), &key, sizeof(key)));
  115. uint8_t value = 1;
  116. size_t value_length = 999999;
  117. EXPECT_TRUE(LoggingWriteFile(fd(), &value_length, sizeof(size_t)));
  118. EXPECT_TRUE(LoggingWriteFile(fd(), &value, sizeof(value)));
  119. EXPECT_EQ(reader.Initialize(dump_interface()), Result::kIncomplete);
  120. EXPECT_FALSE(IsRegularFile(path()));
  121. const auto root_map = reader.RootMap();
  122. EXPECT_TRUE(root_map->empty());
  123. const auto version_data = root_map->GetAsData(Key::kVersion);
  124. EXPECT_EQ(version_data, nullptr);
  125. }
  126. TEST_F(IOSIntermediateDumpReaderTest, InvalidArrayInArray) {
  127. internal::IOSIntermediateDumpReader reader;
  128. {
  129. IOSIntermediateDumpWriter::ScopedRootMap scopedRoot(writer_.get());
  130. IOSIntermediateDumpWriter::ScopedArray threadArray(writer_.get(),
  131. Key::kThreads);
  132. IOSIntermediateDumpWriter::ScopedArray innerThreadArray(writer_.get(),
  133. Key::kModules);
  134. // Write version last, so it's not parsed.
  135. int8_t version = 1;
  136. writer_->AddProperty(Key::kVersion, &version);
  137. }
  138. EXPECT_TRUE(writer_->Close());
  139. EXPECT_EQ(reader.Initialize(dump_interface()), Result::kIncomplete);
  140. EXPECT_FALSE(IsRegularFile(path()));
  141. const auto root_map = reader.RootMap();
  142. EXPECT_FALSE(root_map->empty());
  143. const auto version_data = root_map->GetAsData(Key::kVersion);
  144. EXPECT_EQ(version_data, nullptr);
  145. }
  146. TEST_F(IOSIntermediateDumpReaderTest, InvalidPropertyInArray) {
  147. internal::IOSIntermediateDumpReader reader;
  148. {
  149. IOSIntermediateDumpWriter::ScopedRootMap scopedRoot(writer_.get());
  150. IOSIntermediateDumpWriter::ScopedArray threadArray(writer_.get(),
  151. Key::kThreads);
  152. // Write version last, so it's not parsed.
  153. int8_t version = 1;
  154. writer_->AddProperty(Key::kVersion, &version);
  155. }
  156. EXPECT_TRUE(writer_->Close());
  157. EXPECT_EQ(reader.Initialize(dump_interface()), Result::kIncomplete);
  158. EXPECT_FALSE(IsRegularFile(path()));
  159. const auto root_map = reader.RootMap();
  160. EXPECT_FALSE(root_map->empty());
  161. const auto version_data = root_map->GetAsData(Key::kVersion);
  162. EXPECT_EQ(version_data, nullptr);
  163. }
  164. TEST_F(IOSIntermediateDumpReaderTest, ReadValidData) {
  165. internal::IOSIntermediateDumpReader reader;
  166. uint8_t version = 1;
  167. {
  168. IOSIntermediateDumpWriter::ScopedRootMap scopedRoot(writer_.get());
  169. EXPECT_TRUE(writer_->AddProperty(Key::kVersion, &version));
  170. {
  171. IOSIntermediateDumpWriter::ScopedArray threadArray(
  172. writer_.get(), Key::kThreadContextMemoryRegions);
  173. IOSIntermediateDumpWriter::ScopedArrayMap threadMap(writer_.get());
  174. std::string random_data("random_data");
  175. EXPECT_TRUE(writer_->AddProperty(Key::kThreadContextMemoryRegionAddress,
  176. &version));
  177. EXPECT_TRUE(writer_->AddProperty(Key::kThreadContextMemoryRegionData,
  178. random_data.c_str(),
  179. random_data.length()));
  180. }
  181. {
  182. IOSIntermediateDumpWriter::ScopedMap map(writer_.get(),
  183. Key::kProcessInfo);
  184. pid_t p_pid = getpid();
  185. EXPECT_TRUE(writer_->AddProperty(Key::kPID, &p_pid));
  186. }
  187. }
  188. EXPECT_TRUE(writer_->Close());
  189. EXPECT_EQ(reader.Initialize(dump_interface()), Result::kSuccess);
  190. EXPECT_FALSE(IsRegularFile(path()));
  191. auto root_map = reader.RootMap();
  192. EXPECT_FALSE(root_map->empty());
  193. version = -1;
  194. const auto version_data = root_map->GetAsData(Key::kVersion);
  195. ASSERT_NE(version_data, nullptr);
  196. EXPECT_TRUE(version_data->GetValue<uint8_t>(&version));
  197. EXPECT_EQ(version, 1);
  198. const auto process_info = root_map->GetAsMap(Key::kProcessInfo);
  199. ASSERT_NE(process_info, nullptr);
  200. const auto pid_data = process_info->GetAsData(Key::kPID);
  201. ASSERT_NE(pid_data, nullptr);
  202. pid_t p_pid = -1;
  203. EXPECT_TRUE(pid_data->GetValue<pid_t>(&p_pid));
  204. ASSERT_EQ(p_pid, getpid());
  205. const auto thread_context_memory_regions =
  206. root_map->GetAsList(Key::kThreadContextMemoryRegions);
  207. EXPECT_EQ(thread_context_memory_regions->size(), 1UL);
  208. for (const auto& region : *thread_context_memory_regions) {
  209. const auto data = region->GetAsData(Key::kThreadContextMemoryRegionData);
  210. ASSERT_NE(data, nullptr);
  211. // Load as string.
  212. EXPECT_EQ(data->GetString(), "random_data");
  213. // Load as bytes.
  214. auto bytes = data->bytes();
  215. vm_size_t data_size = bytes.size();
  216. EXPECT_EQ(data_size, 11UL);
  217. const char* data_bytes = reinterpret_cast<const char*>(bytes.data());
  218. EXPECT_EQ(std::string(data_bytes, data_size), "random_data");
  219. }
  220. const auto system_info = root_map->GetAsMap(Key::kSystemInfo);
  221. EXPECT_EQ(system_info, nullptr);
  222. }
  223. } // namespace
  224. } // namespace test
  225. } // namespace crashpad