Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/xpconnect/loader/AutoMemMap.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
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
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "AutoMemMap.h"
8
#include "ScriptPreloader-inl.h"
9
10
#include "mozilla/Unused.h"
11
#include "mozilla/ipc/FileDescriptor.h"
12
#include "nsIFile.h"
13
14
#include <private/pprio.h>
15
16
namespace mozilla {
17
namespace loader {
18
19
using namespace mozilla::ipc;
20
21
AutoMemMap::~AutoMemMap()
22
0
{
23
0
    reset();
24
0
}
25
26
FileDescriptor
27
AutoMemMap::cloneFileDescriptor() const
28
0
{
29
0
    if (fd.get()) {
30
0
        auto handle = FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd.get()));
31
0
        return FileDescriptor(handle);
32
0
    }
33
0
    return FileDescriptor();
34
0
}
35
36
Result<Ok, nsresult>
37
AutoMemMap::init(nsIFile* file, int flags, int mode, PRFileMapProtect prot)
38
0
{
39
0
    MOZ_ASSERT(!fd);
40
0
41
0
    MOZ_TRY(file->OpenNSPRFileDesc(flags, mode, &fd.rwget()));
42
0
43
0
    return initInternal(prot);
44
0
}
45
46
Result<Ok, nsresult>
47
AutoMemMap::init(const FileDescriptor& file, PRFileMapProtect prot,
48
                 size_t expectedSize)
49
0
{
50
0
    MOZ_ASSERT(!fd);
51
0
    if (!file.IsValid()) {
52
0
        return Err(NS_ERROR_INVALID_ARG);
53
0
    }
54
0
55
0
    auto handle = file.ClonePlatformHandle();
56
0
57
0
    fd = PR_ImportFile(PROsfd(handle.get()));
58
0
    if (!fd) {
59
0
        return Err(NS_ERROR_FAILURE);
60
0
    }
61
0
    Unused << handle.release();
62
0
63
0
    return initInternal(prot, expectedSize);
64
0
}
65
66
Result<Ok, nsresult>
67
AutoMemMap::initInternal(PRFileMapProtect prot, size_t expectedSize)
68
0
{
69
0
    MOZ_ASSERT(!fileMap);
70
0
    MOZ_ASSERT(!addr);
71
0
72
0
    PRFileInfo64 fileInfo;
73
0
    MOZ_TRY(PR_GetOpenFileInfo64(fd.get(), &fileInfo));
74
0
75
0
    if (fileInfo.size > UINT32_MAX) {
76
0
        return Err(NS_ERROR_INVALID_ARG);
77
0
    }
78
0
79
0
    fileMap = PR_CreateFileMap(fd, 0, prot);
80
0
    if (!fileMap) {
81
0
        return Err(NS_ERROR_FAILURE);
82
0
    }
83
0
84
0
    size_ = fileInfo.size;
85
0
    // The memory region size passed in certain IPC messages isn't necessary on
86
0
    // Unix-like systems, since we can always stat the file descriptor to
87
0
    // determine it accurately. But since we have it, anyway, sanity check that
88
0
    // it matches the size returned by the stat.
89
0
    MOZ_ASSERT_IF(expectedSize > 0, size_ == expectedSize);
90
0
91
0
    addr = PR_MemMap(fileMap, 0, size_);
92
0
    if (!addr) {
93
0
        return Err(NS_ERROR_FAILURE);
94
0
    }
95
0
96
0
    return Ok();
97
0
}
98
99
#ifdef XP_WIN
100
101
Result<Ok, nsresult>
102
AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot)
103
{
104
    MOZ_ASSERT(!fd);
105
    MOZ_ASSERT(!handle_);
106
    if (!file.IsValid()) {
107
        return Err(NS_ERROR_INVALID_ARG);
108
    }
109
110
    handle_ = file.ClonePlatformHandle().release();
111
112
    MOZ_ASSERT(!addr);
113
114
    size_ = size;
115
116
    addr = MapViewOfFile(
117
          handle_,
118
          prot == PR_PROT_READONLY ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
119
          0, 0, size);
120
121
    return Ok();
122
}
123
124
FileDescriptor
125
AutoMemMap::cloneHandle() const
126
{
127
    return FileDescriptor(handle_);
128
}
129
130
#else
131
132
Result<Ok, nsresult>
133
AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot)
134
0
{
135
0
    return init(file, prot);
136
0
}
137
138
FileDescriptor
139
AutoMemMap::cloneHandle() const
140
0
{
141
0
    return cloneFileDescriptor();
142
0
}
143
144
#endif
145
146
void
147
AutoMemMap::reset()
148
0
{
149
0
    if (addr && !persistent_) {
150
0
        Unused << NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS);
151
0
        addr = nullptr;
152
0
    }
153
0
    if (fileMap) {
154
0
        Unused << NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS);
155
0
        fileMap = nullptr;
156
0
    }
157
#ifdef XP_WIN
158
    if (handle_) {
159
      CloseHandle(handle_);
160
      handle_ = nullptr;
161
    }
162
#endif
163
    fd.dispose();
164
0
}
165
166
} // namespace loader
167
} // namespace mozilla