Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/js/StableStringChars.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
 * Safely access the contents of a string even as GC can cause the string's
8
 * contents to move around in memory.
9
 */
10
11
#ifndef js_StableStringChars_h
12
#define js_StableStringChars_h
13
14
#include "mozilla/Assertions.h" // MOZ_ASSERT
15
#include "mozilla/Attributes.h" // MOZ_INIT_OUTSIDE_CTOR, MOZ_STACK_CLASS, MOZ_MUST_USE
16
#include "mozilla/Maybe.h" // mozilla::Maybe
17
#include "mozilla/Range.h" // mozilla::Range
18
19
#include <stddef.h> // size_t
20
#include <stdint.h> // uint8_t
21
22
#include "jstypes.h" // JS_FRIEND_API
23
24
#include "js/HeapAPI.h" // JS::shadow::String
25
#include "js/RootingAPI.h" // JS::Handle, JS::Rooted
26
#include "js/TypeDecls.h" // JSContext, JS::Latin1Char, JSString
27
#include "js/Vector.h" // js::Vector
28
29
class JSLinearString;
30
31
namespace JS {
32
33
MOZ_ALWAYS_INLINE size_t
34
GetStringLength(JSString* s)
35
14
{
36
14
    return reinterpret_cast<shadow::String*>(s)->length();
37
14
}
38
39
/**
40
 * This class provides safe access to a string's chars across a GC. Once
41
 * we allocate strings and chars in the nursery (bug 903519), this class
42
 * will have to make a copy of the string's chars if they are allocated
43
 * in the nursery, so it's best to avoid using this class unless you really
44
 * need it. It's usually more efficient to use the latin1Chars/twoByteChars
45
 * JSString methods and often the code can be rewritten so that only indexes
46
 * instead of char pointers are used in parts of the code that can GC.
47
 */
48
class MOZ_STACK_CLASS JS_FRIEND_API(AutoStableStringChars) final
49
{
50
    /*
51
     * When copying string char, use this many bytes of inline storage.  This is
52
     * chosen to allow the inline string types to be copied without allocating.
53
     * This is asserted in AutoStableStringChars::allocOwnChars.
54
     */
55
    static const size_t InlineCapacity = 24;
56
57
    /* Ensure the string is kept alive while we're using its chars. */
58
    Rooted<JSString*> s_;
59
    MOZ_INIT_OUTSIDE_CTOR union {
60
        const char16_t* twoByteChars_;
61
        const Latin1Char* latin1Chars_;
62
    };
63
    mozilla::Maybe<js::Vector<uint8_t, InlineCapacity>> ownChars_;
64
    enum State { Uninitialized, Latin1, TwoByte };
65
    State state_;
66
67
  public:
68
    explicit AutoStableStringChars(JSContext* cx)
69
      : s_(cx), state_(Uninitialized)
70
0
    {}
71
72
    MOZ_MUST_USE bool init(JSContext* cx, JSString* s);
73
74
    /* Like init(), but Latin1 chars are inflated to TwoByte. */
75
    MOZ_MUST_USE bool initTwoByte(JSContext* cx, JSString* s);
76
77
0
    bool isLatin1() const { return state_ == Latin1; }
78
0
    bool isTwoByte() const { return state_ == TwoByte; }
79
80
0
    const Latin1Char* latin1Chars() const {
81
0
        MOZ_ASSERT(state_ == Latin1);
82
0
        return latin1Chars_;
83
0
    }
84
0
    const char16_t* twoByteChars() const {
85
0
        MOZ_ASSERT(state_ == TwoByte);
86
0
        return twoByteChars_;
87
0
    }
88
89
0
    mozilla::Range<const Latin1Char> latin1Range() const {
90
0
        MOZ_ASSERT(state_ == Latin1);
91
0
        return mozilla::Range<const Latin1Char>(latin1Chars_, GetStringLength(s_));
92
0
    }
93
94
0
    mozilla::Range<const char16_t> twoByteRange() const {
95
0
        MOZ_ASSERT(state_ == TwoByte);
96
0
        return mozilla::Range<const char16_t>(twoByteChars_,
97
0
                                              GetStringLength(s_));
98
0
    }
99
100
    /* If we own the chars, transfer ownership to the caller. */
101
0
    bool maybeGiveOwnershipToCaller() {
102
0
        MOZ_ASSERT(state_ != Uninitialized);
103
0
        if (!ownChars_.isSome() || !ownChars_->extractRawBuffer()) {
104
0
            return false;
105
0
        }
106
0
        state_ = Uninitialized;
107
0
        ownChars_.reset();
108
0
        return true;
109
0
    }
110
111
  private:
112
    AutoStableStringChars(const AutoStableStringChars& other) = delete;
113
    void operator=(const AutoStableStringChars& other) = delete;
114
115
    bool baseIsInline(Handle<JSLinearString*> linearString);
116
    template <typename T> T* allocOwnChars(JSContext* cx, size_t count);
117
    bool copyLatin1Chars(JSContext* cx, Handle<JSLinearString*> linearString);
118
    bool copyTwoByteChars(JSContext* cx, Handle<JSLinearString*> linearString);
119
    bool copyAndInflateLatin1Chars(JSContext*, Handle<JSLinearString*> linearString);
120
};
121
122
} // namespace JS
123
124
#endif /* js_StableStringChars_h */