/src/mozilla-central/tools/fuzzing/libfuzzer/FuzzerShmemPosix.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // SharedMemoryRegion |
10 | | //===----------------------------------------------------------------------===// |
11 | | #include "FuzzerDefs.h" |
12 | | #if LIBFUZZER_POSIX |
13 | | |
14 | | #include "FuzzerIO.h" |
15 | | #include "FuzzerShmem.h" |
16 | | |
17 | | #include <errno.h> |
18 | | #include <fcntl.h> |
19 | | #include <semaphore.h> |
20 | | #include <stdio.h> |
21 | | #include <stdlib.h> |
22 | | #include <sys/mman.h> |
23 | | #include <sys/stat.h> |
24 | | #include <sys/types.h> |
25 | | #include <unistd.h> |
26 | | |
27 | | namespace fuzzer { |
28 | | |
29 | 0 | std::string SharedMemoryRegion::Path(const char *Name) { |
30 | 0 | return DirPlusFile(TmpDir(), Name); |
31 | 0 | } |
32 | | |
33 | 0 | std::string SharedMemoryRegion::SemName(const char *Name, int Idx) { |
34 | 0 | std::string Res(Name); |
35 | 0 | // When passing a name without a leading <slash> character to |
36 | 0 | // sem_open, the behaviour is unspecified in POSIX. Add a leading |
37 | 0 | // <slash> character for the name if there is no such one. |
38 | 0 | if (!Res.empty() && Res[0] != '/') |
39 | 0 | Res.insert(Res.begin(), '/'); |
40 | 0 | return Res + (char)('0' + Idx); |
41 | 0 | } |
42 | | |
43 | 0 | bool SharedMemoryRegion::Map(int fd) { |
44 | 0 | Data = |
45 | 0 | (uint8_t *)mmap(0, kShmemSize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); |
46 | 0 | if (Data == (uint8_t*)-1) |
47 | 0 | return false; |
48 | 0 | return true; |
49 | 0 | } |
50 | | |
51 | 0 | bool SharedMemoryRegion::Create(const char *Name) { |
52 | 0 | int fd = open(Path(Name).c_str(), O_CREAT | O_RDWR, 0777); |
53 | 0 | if (fd < 0) return false; |
54 | 0 | if (ftruncate(fd, kShmemSize) < 0) return false; |
55 | 0 | if (!Map(fd)) |
56 | 0 | return false; |
57 | 0 | for (int i = 0; i < 2; i++) { |
58 | 0 | sem_unlink(SemName(Name, i).c_str()); |
59 | 0 | Semaphore[i] = sem_open(SemName(Name, i).c_str(), O_CREAT, 0644, 0); |
60 | 0 | if (Semaphore[i] == SEM_FAILED) |
61 | 0 | return false; |
62 | 0 | } |
63 | 0 | IAmServer = true; |
64 | 0 | return true; |
65 | 0 | } |
66 | | |
67 | 0 | bool SharedMemoryRegion::Open(const char *Name) { |
68 | 0 | int fd = open(Path(Name).c_str(), O_RDWR); |
69 | 0 | if (fd < 0) return false; |
70 | 0 | struct stat stat_res; |
71 | 0 | if (0 != fstat(fd, &stat_res)) |
72 | 0 | return false; |
73 | 0 | assert(stat_res.st_size == kShmemSize); |
74 | 0 | if (!Map(fd)) |
75 | 0 | return false; |
76 | 0 | for (int i = 0; i < 2; i++) { |
77 | 0 | Semaphore[i] = sem_open(SemName(Name, i).c_str(), 0); |
78 | 0 | if (Semaphore[i] == SEM_FAILED) |
79 | 0 | return false; |
80 | 0 | } |
81 | 0 | IAmServer = false; |
82 | 0 | return true; |
83 | 0 | } |
84 | | |
85 | 0 | bool SharedMemoryRegion::Destroy(const char *Name) { |
86 | 0 | return 0 == unlink(Path(Name).c_str()); |
87 | 0 | } |
88 | | |
89 | 0 | void SharedMemoryRegion::Post(int Idx) { |
90 | 0 | assert(Idx == 0 || Idx == 1); |
91 | 0 | sem_post((sem_t*)Semaphore[Idx]); |
92 | 0 | } |
93 | | |
94 | 0 | void SharedMemoryRegion::Wait(int Idx) { |
95 | 0 | assert(Idx == 0 || Idx == 1); |
96 | 0 | for (int i = 0; i < 10 && sem_wait((sem_t*)Semaphore[Idx]); i++) { |
97 | 0 | // sem_wait may fail if interrupted by a signal. |
98 | 0 | sleep(i); |
99 | 0 | if (i) |
100 | 0 | Printf("%s: sem_wait[%d] failed %s\n", i < 9 ? "WARNING" : "ERROR", i, |
101 | 0 | strerror(errno)); |
102 | 0 | if (i == 9) abort(); |
103 | 0 | } |
104 | 0 | } |
105 | | |
106 | | } // namespace fuzzer |
107 | | |
108 | | #endif // LIBFUZZER_POSIX |