Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/js/SourceBufferHolder.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; 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
/*
7
 * SourceBufferHolder groups buffer and length values and provides a way to
8
 * optionally pass ownership of the buffer to the JS engine without copying.
9
 *
10
 * Rules for use:
11
 *
12
 *  1) The data array must be allocated with js_malloc() or js_realloc() if
13
 *     ownership is being granted to the SourceBufferHolder.
14
 *  2) If ownership is not given to the SourceBufferHolder, then the memory
15
 *     must be kept alive until the JS compilation is complete.
16
 *  3) Any code calling SourceBufferHolder::take() must guarantee to keep the
17
 *     memory alive until JS compilation completes.  Normally only the JS
18
 *     engine should be calling take().
19
 *
20
 * Example use:
21
 *
22
 *    size_t length = 512;
23
 *    char16_t* chars = js_pod_malloc<char16_t>(length);
24
 *    JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
25
 *    JS::Compile(cx, options, srcBuf);
26
 */
27
28
#ifndef js_SourceBufferHolder_h
29
#define js_SourceBufferHolder_h
30
31
#include "mozilla/Assertions.h" // MOZ_ASSERT
32
33
#include <stddef.h> // size_t
34
35
#include "js/Utility.h" // JS::UniqueTwoByteChars
36
37
namespace JS {
38
39
class SourceBufferHolder final
40
{
41
  private:
42
    const char16_t* data_;
43
    size_t length_;
44
    bool ownsChars_;
45
46
  private:
47
8
    void fixEmptyBuffer() {
48
8
        // Ensure that null buffers properly return an unowned, empty,
49
8
        // null-terminated string.
50
8
        static const char16_t NullChar_ = 0;
51
8
        if (!data_) {
52
0
            data_ = &NullChar_;
53
0
            length_ = 0;
54
0
            ownsChars_ = false;
55
0
        }
56
8
    }
57
58
  public:
59
    enum Ownership {
60
      NoOwnership,
61
      GiveOwnership
62
    };
63
64
    SourceBufferHolder(const char16_t* data, size_t dataLength, Ownership ownership)
65
      : data_(data),
66
        length_(dataLength),
67
        ownsChars_(ownership == GiveOwnership)
68
8
    {
69
8
        fixEmptyBuffer();
70
8
    }
71
72
    SourceBufferHolder(UniqueTwoByteChars&& data, size_t dataLength)
73
      : data_(data.release()),
74
        length_(dataLength),
75
        ownsChars_(true)
76
0
    {
77
0
        fixEmptyBuffer();
78
0
    }
79
80
    SourceBufferHolder(SourceBufferHolder&& other)
81
      : data_(other.data_),
82
        length_(other.length_),
83
        ownsChars_(other.ownsChars_)
84
0
    {
85
0
        other.data_ = nullptr;
86
0
        other.length_ = 0;
87
0
        other.ownsChars_ = false;
88
0
    }
89
90
8
    ~SourceBufferHolder() {
91
8
        if (ownsChars_) {
92
8
            js_free(const_cast<char16_t*>(data_));
93
8
        }
94
8
    }
95
96
    /** Access the underlying source buffer without affecting ownership. */
97
8
    const char16_t* get() const {
98
8
        return data_;
99
8
    }
100
101
    /** Length of the source buffer in char16_t code units (not bytes). */
102
32
    size_t length() const {
103
32
        return length_;
104
32
    }
105
106
    /**
107
     * Returns true if the SourceBufferHolder owns the buffer and will free it
108
     * upon destruction.  If true, it is legal to call take().
109
     */
110
0
    bool ownsChars() const {
111
0
        return ownsChars_;
112
0
    }
113
114
    /**
115
     * Retrieve and take ownership of the underlying data buffer.  The caller
116
     * is now responsible for calling js_free() on the returned value, *but
117
     * only after JS script compilation has completed*.
118
     *
119
     * After the buffer has been taken the SourceBufferHolder functions as if
120
     * it had been constructed on an unowned buffer;  get() and length() still
121
     * work.  In order for this to be safe the taken buffer must be kept alive
122
     * until after JS script compilation completes as noted above.
123
     *
124
     * It's the caller's responsibility to check ownsChars() before taking the
125
     * buffer.  Taking and then free'ing an unowned buffer will have dire
126
     * consequences.
127
     */
128
0
    char16_t* take() {
129
0
        MOZ_ASSERT(ownsChars_);
130
0
        ownsChars_ = false;
131
0
        return const_cast<char16_t*>(data_);
132
0
    }
133
134
  private:
135
    SourceBufferHolder(SourceBufferHolder&) = delete;
136
    SourceBufferHolder& operator=(SourceBufferHolder&) = delete;
137
};
138
139
} // namespace JS
140
141
#endif /* js_SourceBufferHolder_h */