Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/xpconnect/loader/ScriptPreloader-inl.h
Line
Count
Source (jump to first uncovered line)
1
/* -*-  Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#ifndef ScriptPreloader_inl_h
7
#define ScriptPreloader_inl_h
8
9
#include "mozilla/Attributes.h"
10
#include "mozilla/Assertions.h"
11
#include "mozilla/CheckedInt.h"
12
#include "mozilla/EndianUtils.h"
13
#include "mozilla/EnumSet.h"
14
#include "mozilla/Range.h"
15
#include "mozilla/ResultExtensions.h"
16
#include "mozilla/Unused.h"
17
#include "mozilla/dom/ScriptSettings.h"
18
#include "nsString.h"
19
#include "nsTArray.h"
20
21
#include <prio.h>
22
23
namespace mozilla {
24
25
namespace loader {
26
27
using mozilla::dom::AutoJSAPI;
28
29
static inline Result<Ok, nsresult>
30
Write(PRFileDesc* fd, const void* data, int32_t len)
31
0
{
32
0
    if (PR_Write(fd, data, len) != len) {
33
0
        return Err(NS_ERROR_FAILURE);
34
0
    }
35
0
    return Ok();
36
0
}
Unexecuted instantiation: mozJSComponentLoader.cpp:mozilla::loader::Write(PRFileDesc*, void const*, int)
Unexecuted instantiation: Unified_cpp_js_xpconnect_loader0.cpp:mozilla::loader::Write(PRFileDesc*, void const*, int)
Unexecuted instantiation: Unified_cpp_dom_ipc0.cpp:mozilla::loader::Write(PRFileDesc*, void const*, int)
Unexecuted instantiation: Unified_cpp_dom_ipc1.cpp:mozilla::loader::Write(PRFileDesc*, void const*, int)
37
38
struct MOZ_RAII AutoSafeJSAPI : public AutoJSAPI
39
{
40
12
    AutoSafeJSAPI() { Init(); }
41
};
42
43
44
class OutputBuffer
45
{
46
public:
47
    OutputBuffer()
48
0
    {}
49
50
    uint8_t*
51
    write(size_t size)
52
0
    {
53
0
        auto buf = data.AppendElements(size);
54
0
        cursor_ += size;
55
0
        return buf;
56
0
    }
57
58
    void
59
    codeUint8(const uint8_t& val)
60
0
    {
61
0
        *write(sizeof val) = val;
62
0
    }
63
64
    template<typename T>
65
    void
66
    codeUint8(const EnumSet<T>& val)
67
0
    {
68
0
        // EnumSets are always represented as uint32_t values, so we need to
69
0
        // assert that the value actually fits in a uint8 before writing it.
70
0
        uint32_t value = val.serialize();
71
0
        codeUint8(CheckedUint8(value).value());
72
0
    }
73
74
    void
75
    codeUint16(const uint16_t& val)
76
0
    {
77
0
        LittleEndian::writeUint16(write(sizeof val), val);
78
0
    }
79
80
    void
81
    codeUint32(const uint32_t& val)
82
0
    {
83
0
        LittleEndian::writeUint32(write(sizeof val), val);
84
0
    }
85
86
    void
87
    codeString(const nsCString& str)
88
0
    {
89
0
        auto len = CheckedUint16(str.Length()).value();
90
0
91
0
        codeUint16(len);
92
0
        memcpy(write(len), str.BeginReading(), len);
93
0
    }
94
95
0
    size_t cursor() const { return cursor_; }
96
97
98
0
    uint8_t* Get() { return data.Elements(); }
99
100
0
    const uint8_t* Get() const { return data.Elements(); }
101
102
private:
103
    nsTArray<uint8_t> data;
104
    size_t cursor_ = 0;
105
};
106
107
class InputBuffer
108
{
109
public:
110
    explicit InputBuffer(const Range<uint8_t>& buffer)
111
        : data(buffer)
112
0
    {}
113
114
    const uint8_t*
115
    read(size_t size)
116
0
    {
117
0
        MOZ_ASSERT(checkCapacity(size));
118
0
119
0
        auto buf = &data[cursor_];
120
0
        cursor_ += size;
121
0
        return buf;
122
0
    }
123
124
    bool
125
    codeUint8(uint8_t& val)
126
0
    {
127
0
        if (checkCapacity(sizeof val)) {
128
0
            val = *read(sizeof val);
129
0
        }
130
0
        return !error_;
131
0
    }
132
133
    template<typename T>
134
    bool
135
    codeUint8(EnumSet<T>& val)
136
0
    {
137
0
        uint8_t value;
138
0
        if (codeUint8(value)) {
139
0
            val.deserialize(value);
140
0
        }
141
0
        return !error_;
142
0
    }
143
144
    bool
145
    codeUint16(uint16_t& val)
146
0
    {
147
0
        if (checkCapacity(sizeof val)) {
148
0
            val = LittleEndian::readUint16(read(sizeof val));
149
0
        }
150
0
        return !error_;
151
0
    }
152
153
    bool
154
    codeUint32(uint32_t& val)
155
0
    {
156
0
        if (checkCapacity(sizeof val)) {
157
0
            val = LittleEndian::readUint32(read(sizeof val));
158
0
        }
159
0
        return !error_;
160
0
    }
161
162
    bool
163
    codeString(nsCString& str)
164
0
    {
165
0
        uint16_t len;
166
0
        if (codeUint16(len)) {
167
0
            if (checkCapacity(len)) {
168
0
                str.SetLength(len);
169
0
                memcpy(str.BeginWriting(), read(len), len);
170
0
            }
171
0
        }
172
0
        return !error_;
173
0
    }
174
175
0
    bool error() { return error_; }
176
177
0
    bool finished() { return error_ || !remainingCapacity(); }
178
179
0
    size_t remainingCapacity() { return data.length() - cursor_; }
180
181
0
    size_t cursor() const { return cursor_; }
182
183
0
    const uint8_t* Get() const { return data.begin().get(); }
184
185
private:
186
    bool
187
    checkCapacity(size_t size)
188
0
    {
189
0
        if (size > remainingCapacity()) {
190
0
            error_ = true;
191
0
        }
192
0
        return !error_;
193
0
    }
194
195
    bool error_ = false;
196
197
public:
198
    const Range<uint8_t>& data;
199
    size_t cursor_ = 0;
200
};
201
202
203
template <typename T> struct Matcher;
204
205
// Wraps the iterator for a nsTHashTable so that it may be used as a range
206
// iterator. Each iterator result acts as a smart pointer to the hash element,
207
// and has a Remove() method which will remove the element from the hash.
208
//
209
// It also accepts an optional Matcher instance against which to filter the
210
// elements which should be iterated over.
211
//
212
// Example:
213
//
214
//    for (auto& elem : HashElemIter<HashType>(hash)) {
215
//        if (elem->IsDead()) {
216
//            elem.Remove();
217
//        }
218
//    }
219
template <typename T>
220
class HashElemIter
221
{
222
    using Iterator = typename T::Iterator;
223
    using ElemType = typename T::UserDataType;
224
225
    T& hash_;
226
    Matcher<ElemType>* matcher_;
227
    Maybe<Iterator> iter_;
228
229
public:
230
    explicit HashElemIter(T& hash, Matcher<ElemType>* matcher = nullptr)
231
        : hash_(hash), matcher_(matcher)
232
36
    {
233
36
        iter_.emplace(std::move(hash.Iter()));
234
36
    }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::HashElemIter(nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript>&, mozilla::loader::Matcher<mozilla::ScriptPreloader::CachedScript*>*)
Line
Count
Source
232
36
    {
233
36
        iter_.emplace(std::move(hash.Iter()));
234
36
    }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::HashElemIter(nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry>&, mozilla::loader::Matcher<mozilla::URLPreloader::URLEntry*>*)
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::HashElemIter(nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry>&, mozilla::loader::Matcher<mozilla::dom::ipc::SharedMap::Entry*>*)
235
236
    class Elem
237
    {
238
        friend class HashElemIter<T>;
239
240
        HashElemIter<T>& iter_;
241
        bool done_;
242
243
        Elem(HashElemIter& iter, bool done)
244
            : iter_(iter), done_(done)
245
72
        {
246
72
            skipNonMatching();
247
72
        }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::Elem(mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >&, bool)
Line
Count
Source
245
72
        {
246
72
            skipNonMatching();
247
72
        }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::Elem(mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >&, bool)
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::Elem(mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >&, bool)
248
249
270
        Iterator& iter() { return iter_.iter_.ref(); }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::iter()
Line
Count
Source
249
270
        Iterator& iter() { return iter_.iter_.ref(); }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::iter()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::iter()
250
251
        void skipNonMatching()
252
162
        {
253
162
            if (iter_.matcher_) {
254
0
                while (!done_ && !iter_.matcher_->Matches(get())) {
255
0
                    iter().Next();
256
0
                    done_ = iter().Done();
257
0
                }
258
0
            }
259
162
        }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::skipNonMatching()
Line
Count
Source
252
162
        {
253
162
            if (iter_.matcher_) {
254
0
                while (!done_ && !iter_.matcher_->Matches(get())) {
255
0
                    iter().Next();
256
0
                    done_ = iter().Done();
257
0
                }
258
0
            }
259
162
        }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::skipNonMatching()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::skipNonMatching()
260
261
    public:
262
90
        Elem& operator*() { return *this; }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::operator*()
Line
Count
Source
262
90
        Elem& operator*() { return *this; }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::operator*()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::operator*()
263
264
        ElemType get()
265
162
        {
266
162
          if (done_) {
267
72
            return nullptr;
268
72
          }
269
90
          return iter().Data();
270
90
        }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::get()
Line
Count
Source
265
162
        {
266
162
          if (done_) {
267
72
            return nullptr;
268
72
          }
269
90
          return iter().Data();
270
90
        }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::get()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::get()
271
272
        const ElemType get() const
273
0
        {
274
0
          return const_cast<Elem*>(this)->get();
275
0
        }
276
277
90
        ElemType operator->() { return get(); }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::operator->()
Line
Count
Source
277
90
        ElemType operator->() { return get(); }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::operator->()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::operator->()
278
279
0
        const ElemType operator->() const { return get(); }
280
281
0
        operator ElemType() { return get(); }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::operator mozilla::ScriptPreloader::CachedScript*()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::operator mozilla::URLPreloader::URLEntry*()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::operator mozilla::dom::ipc::SharedMap::Entry*()
282
283
0
        void Remove() { iter().Remove(); }
284
285
        Elem& operator++()
286
90
        {
287
90
            MOZ_ASSERT(!done_);
288
90
289
90
            iter().Next();
290
90
            done_ = iter().Done();
291
90
292
90
            skipNonMatching();
293
90
            return *this;
294
90
        }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::operator++()
Line
Count
Source
286
90
        {
287
90
            MOZ_ASSERT(!done_);
288
90
289
90
            iter().Next();
290
90
            done_ = iter().Done();
291
90
292
90
            skipNonMatching();
293
90
            return *this;
294
90
        }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::operator++()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::operator++()
295
296
        bool operator!=(Elem& other)
297
126
        {
298
126
            return done_ != other.done_ || this->get() != other.get();
299
126
        }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem::operator!=(mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::Elem&)
Line
Count
Source
297
126
        {
298
126
            return done_ != other.done_ || this->get() != other.get();
299
126
        }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem::operator!=(mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::Elem&)
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem::operator!=(mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::Elem&)
300
    };
301
302
36
    Elem begin() { return Elem(*this, iter_->Done()); }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::begin()
Line
Count
Source
302
36
    Elem begin() { return Elem(*this, iter_->Done()); }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::begin()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::begin()
303
304
36
    Elem end() { return Elem(*this, true); }
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >::end()
Line
Count
Source
304
36
    Elem end() { return Elem(*this, true); }
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >::end()
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >::end()
305
};
306
307
template <typename T>
308
HashElemIter<T> IterHash(T& hash, Matcher<typename T::UserDataType>* matcher = nullptr)
309
36
{
310
36
    return HashElemIter<T>(hash, matcher);
311
36
}
mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> > mozilla::loader::IterHash<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript> >(nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript>&, mozilla::loader::Matcher<nsClassHashtable<nsCStringHashKey, mozilla::ScriptPreloader::CachedScript>::UserDataType>*)
Line
Count
Source
309
36
{
310
36
    return HashElemIter<T>(hash, matcher);
311
36
}
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> > mozilla::loader::IterHash<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry> >(nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry>&, mozilla::loader::Matcher<nsClassHashtable<nsGenericHashKey<mozilla::URLPreloader::CacheKey>, mozilla::URLPreloader::URLEntry>::UserDataType>*)
Unexecuted instantiation: mozilla::loader::HashElemIter<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> > mozilla::loader::IterHash<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry> >(nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry>&, mozilla::loader::Matcher<nsClassHashtable<nsCStringHashKey, mozilla::dom::ipc::SharedMap::Entry>::UserDataType>*)
312
313
template <typename T, typename F>
314
bool
315
Find(T&& iter, F&& match)
316
{
317
    for (auto& elem : iter) {
318
        if (match(elem)) {
319
            return true;
320
        }
321
    }
322
    return false;
323
}
324
325
}; // namespace loader
326
}; // namespace mozilla
327
328
#endif // ScriptPreloader_inl_h