proc_maps_linux_unittest.cc
1 // Copyright 2013 Google LLC 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifdef HAVE_CONFIG_H 6 #include <config.h> // Must come first 7 #endif 8 9 #include "breakpad_googletest_includes.h" 10 #include "common/using_std_string.h" 11 #include "google_breakpad/processor/proc_maps_linux.h" 12 13 namespace { 14 15 TEST(ProcMapsTest, Empty) { 16 std::vector<google_breakpad::MappedMemoryRegion> regions; 17 EXPECT_TRUE(ParseProcMaps("", ®ions)); 18 EXPECT_EQ(0u, regions.size()); 19 } 20 21 TEST(ProcMapsTest, NoSpaces) { 22 static const char kNoSpaces[] = 23 "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat\n"; 24 25 std::vector<google_breakpad::MappedMemoryRegion> regions; 26 ASSERT_TRUE(ParseProcMaps(kNoSpaces, ®ions)); 27 ASSERT_EQ(1u, regions.size()); 28 29 EXPECT_EQ(0x00400000u, regions[0].start); 30 EXPECT_EQ(0x0040b000u, regions[0].end); 31 EXPECT_EQ(0x00002200u, regions[0].offset); 32 EXPECT_EQ("/bin/cat", regions[0].path); 33 } 34 35 TEST(ProcMapsTest, Spaces) { 36 static const char kSpaces[] = 37 "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/space cat\n"; 38 39 std::vector<google_breakpad::MappedMemoryRegion> regions; 40 ASSERT_TRUE(ParseProcMaps(kSpaces, ®ions)); 41 ASSERT_EQ(1u, regions.size()); 42 43 EXPECT_EQ(0x00400000u, regions[0].start); 44 EXPECT_EQ(0x0040b000u, regions[0].end); 45 EXPECT_EQ(0x00002200u, regions[0].offset); 46 EXPECT_EQ("/bin/space cat", regions[0].path); 47 } 48 49 TEST(ProcMapsTest, NoNewline) { 50 static const char kNoSpaces[] = 51 "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat"; 52 53 std::vector<google_breakpad::MappedMemoryRegion> regions; 54 ASSERT_FALSE(ParseProcMaps(kNoSpaces, ®ions)); 55 } 56 57 TEST(ProcMapsTest, NoPath) { 58 static const char kNoPath[] = 59 "00400000-0040b000 rw-p 00000000 00:00 0 \n"; 60 61 std::vector<google_breakpad::MappedMemoryRegion> regions; 62 ASSERT_TRUE(ParseProcMaps(kNoPath, ®ions)); 63 ASSERT_EQ(1u, regions.size()); 64 65 EXPECT_EQ(0x00400000u, regions[0].start); 66 EXPECT_EQ(0x0040b000u, regions[0].end); 67 EXPECT_EQ(0x00000000u, regions[0].offset); 68 EXPECT_EQ("", regions[0].path); 69 } 70 71 TEST(ProcMapsTest, Heap) { 72 static const char kHeap[] = 73 "022ac000-022cd000 rw-p 00000000 00:00 0 [heap]\n"; 74 75 std::vector<google_breakpad::MappedMemoryRegion> regions; 76 ASSERT_TRUE(ParseProcMaps(kHeap, ®ions)); 77 ASSERT_EQ(1u, regions.size()); 78 79 EXPECT_EQ(0x022ac000u, regions[0].start); 80 EXPECT_EQ(0x022cd000u, regions[0].end); 81 EXPECT_EQ(0x00000000u, regions[0].offset); 82 EXPECT_EQ("[heap]", regions[0].path); 83 } 84 85 #if defined(ARCH_CPU_32_BITS) 86 TEST(ProcMapsTest, Stack32) { 87 static const char kStack[] = 88 "beb04000-beb25000 rw-p 00000000 00:00 0 [stack]\n"; 89 90 std::vector<google_breakpad::MappedMemoryRegion> regions; 91 ASSERT_TRUE(ParseProcMaps(kStack, ®ions)); 92 ASSERT_EQ(1u, regions.size()); 93 94 EXPECT_EQ(0xbeb04000u, regions[0].start); 95 EXPECT_EQ(0xbeb25000u, regions[0].end); 96 EXPECT_EQ(0x00000000u, regions[0].offset); 97 EXPECT_EQ("[stack]", regions[0].path); 98 } 99 #elif defined(ARCH_CPU_64_BITS) 100 TEST(ProcMapsTest, Stack64) { 101 static const char kStack[] = 102 "7fff69c5b000-7fff69c7d000 rw-p 00000000 00:00 0 [stack]\n"; 103 104 std::vector<google_breakpad::MappedMemoryRegion> regions; 105 ASSERT_TRUE(ParseProcMaps(kStack, ®ions)); 106 ASSERT_EQ(1u, regions.size()); 107 108 EXPECT_EQ(0x7fff69c5b000u, regions[0].start); 109 EXPECT_EQ(0x7fff69c7d000u, regions[0].end); 110 EXPECT_EQ(0x00000000u, regions[0].offset); 111 EXPECT_EQ("[stack]", regions[0].path); 112 } 113 #endif 114 115 TEST(ProcMapsTest, Multiple) { 116 static const char kMultiple[] = 117 "00400000-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n" 118 "0060a000-0060b000 r--p 0000a000 fc:00 794418 /bin/cat\n" 119 "0060b000-0060c000 rw-p 0000b000 fc:00 794418 /bin/cat\n"; 120 121 std::vector<google_breakpad::MappedMemoryRegion> regions; 122 ASSERT_TRUE(ParseProcMaps(kMultiple, ®ions)); 123 ASSERT_EQ(3u, regions.size()); 124 125 EXPECT_EQ(0x00400000u, regions[0].start); 126 EXPECT_EQ(0x0040b000u, regions[0].end); 127 EXPECT_EQ(0x00000000u, regions[0].offset); 128 EXPECT_EQ("/bin/cat", regions[0].path); 129 130 EXPECT_EQ(0x0060a000u, regions[1].start); 131 EXPECT_EQ(0x0060b000u, regions[1].end); 132 EXPECT_EQ(0x0000a000u, regions[1].offset); 133 EXPECT_EQ("/bin/cat", regions[1].path); 134 135 EXPECT_EQ(0x0060b000u, regions[2].start); 136 EXPECT_EQ(0x0060c000u, regions[2].end); 137 EXPECT_EQ(0x0000b000u, regions[2].offset); 138 EXPECT_EQ("/bin/cat", regions[2].path); 139 } 140 141 TEST(ProcMapsTest, Permissions) { 142 static struct { 143 const char* input; 144 uint8_t permissions; 145 } kTestCases[] = { 146 {"00400000-0040b000 ---s 00000000 fc:00 794418 /bin/cat\n", 0}, 147 {"00400000-0040b000 ---S 00000000 fc:00 794418 /bin/cat\n", 0}, 148 {"00400000-0040b000 r--s 00000000 fc:00 794418 /bin/cat\n", 149 google_breakpad::MappedMemoryRegion::READ}, 150 {"00400000-0040b000 -w-s 00000000 fc:00 794418 /bin/cat\n", 151 google_breakpad::MappedMemoryRegion::WRITE}, 152 {"00400000-0040b000 --xs 00000000 fc:00 794418 /bin/cat\n", 153 google_breakpad::MappedMemoryRegion::EXECUTE}, 154 {"00400000-0040b000 rwxs 00000000 fc:00 794418 /bin/cat\n", 155 google_breakpad::MappedMemoryRegion::READ 156 | google_breakpad::MappedMemoryRegion::WRITE 157 | google_breakpad::MappedMemoryRegion::EXECUTE}, 158 {"00400000-0040b000 ---p 00000000 fc:00 794418 /bin/cat\n", 159 google_breakpad::MappedMemoryRegion::PRIVATE}, 160 {"00400000-0040b000 r--p 00000000 fc:00 794418 /bin/cat\n", 161 google_breakpad::MappedMemoryRegion::READ 162 | google_breakpad::MappedMemoryRegion::PRIVATE}, 163 {"00400000-0040b000 -w-p 00000000 fc:00 794418 /bin/cat\n", 164 google_breakpad::MappedMemoryRegion::WRITE 165 | google_breakpad::MappedMemoryRegion::PRIVATE}, 166 {"00400000-0040b000 --xp 00000000 fc:00 794418 /bin/cat\n", 167 google_breakpad::MappedMemoryRegion::EXECUTE 168 | google_breakpad::MappedMemoryRegion::PRIVATE}, 169 {"00400000-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n", 170 google_breakpad::MappedMemoryRegion::READ 171 | google_breakpad::MappedMemoryRegion::WRITE 172 | google_breakpad::MappedMemoryRegion::EXECUTE 173 | google_breakpad::MappedMemoryRegion::PRIVATE}, 174 }; 175 176 for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) { 177 std::vector<google_breakpad::MappedMemoryRegion> regions; 178 EXPECT_TRUE(ParseProcMaps(kTestCases[i].input, ®ions)); 179 EXPECT_EQ(1u, regions.size()); 180 if (regions.empty()) 181 continue; 182 EXPECT_EQ(kTestCases[i].permissions, regions[0].permissions); 183 } 184 } 185 186 TEST(ProcMapsTest, MissingFields) { 187 static const char* kTestCases[] = { 188 "00400000\n", // Missing end + beyond. 189 "00400000-0040b000\n", // Missing perms + beyond. 190 "00400000-0040b000 r-xp\n", // Missing offset + beyond. 191 "00400000-0040b000 r-xp 00000000\n", // Missing device + beyond. 192 "00400000-0040b000 r-xp 00000000 fc:00\n", // Missing inode + beyond. 193 "00400000-0040b000 00000000 fc:00 794418 /bin/cat\n", // Missing perms. 194 "00400000-0040b000 r-xp fc:00 794418 /bin/cat\n", // Missing offset. 195 "00400000-0040b000 r-xp 00000000 fc:00 /bin/cat\n", // Missing inode. 196 "00400000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing end. 197 "-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing start. 198 "00400000-0040b000 r-xp 00000000 794418 /bin/cat\n", // Missing device. 199 }; 200 201 for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) { 202 std::vector<google_breakpad::MappedMemoryRegion> regions; 203 EXPECT_FALSE(ParseProcMaps(kTestCases[i], ®ions)); 204 } 205 } 206 207 TEST(ProcMapsTest, InvalidInput) { 208 static const char* kTestCases[] = { 209 "thisisal-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n", 210 "0040000d-linvalid rwxp 00000000 fc:00 794418 /bin/cat\n", 211 "00400000-0040b000 inpu 00000000 fc:00 794418 /bin/cat\n", 212 "00400000-0040b000 rwxp tforproc fc:00 794418 /bin/cat\n", 213 "00400000-0040b000 rwxp 00000000 ma:ps 794418 /bin/cat\n", 214 "00400000-0040b000 rwxp 00000000 fc:00 parse! /bin/cat\n", 215 }; 216 217 for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) { 218 std::vector<google_breakpad::MappedMemoryRegion> regions; 219 EXPECT_FALSE(ParseProcMaps(kTestCases[i], ®ions)); 220 } 221 } 222 223 TEST(ProcMapsTest, ParseProcMapsEmptyString) { 224 std::vector<google_breakpad::MappedMemoryRegion> regions; 225 EXPECT_TRUE(ParseProcMaps("", ®ions)); 226 EXPECT_EQ(0ULL, regions.size()); 227 } 228 229 // Testing a couple of remotely possible weird things in the input: 230 // - Line ending with \r\n or \n\r. 231 // - File name contains quotes. 232 // - File name has whitespaces. 233 TEST(ProcMapsTest, ParseProcMapsWeirdCorrectInput) { 234 std::vector<google_breakpad::MappedMemoryRegion> regions; 235 const string kContents = 236 "00400000-0040b000 r-xp 00000000 fc:00 2106562 " 237 " /bin/cat\r\n" 238 "7f53b7dad000-7f53b7f62000 r-xp 00000000 fc:00 263011 " 239 " /lib/x86_64-linux-gnu/libc-2.15.so\n\r" 240 "7f53b816d000-7f53b818f000 r-xp 00000000 fc:00 264284 " 241 " /lib/x86_64-linux-gnu/ld-2.15.so\n" 242 "7fff9c7ff000-7fff9c800000 r-xp 00000000 00:00 0 " 243 " \"vd so\"\n" 244 "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 " 245 " [vsys call]\n"; 246 EXPECT_TRUE(ParseProcMaps(kContents, ®ions)); 247 EXPECT_EQ(5ULL, regions.size()); 248 EXPECT_EQ("/bin/cat", regions[0].path); 249 EXPECT_EQ("/lib/x86_64-linux-gnu/libc-2.15.so", regions[1].path); 250 EXPECT_EQ("/lib/x86_64-linux-gnu/ld-2.15.so", regions[2].path); 251 EXPECT_EQ("\"vd so\"", regions[3].path); 252 EXPECT_EQ("[vsys call]", regions[4].path); 253 } 254 255 } // namespace