Ignore:
Timestamp:
Dec 18, 2015, 6:32:46 PM (9 years ago)
Author:
[email protected]
Message:

Make JSString::SafeView less of a footgun.
<https://webkit.org/b/152376>

Reviewed by Darin Adler.

Remove the "operator StringView()" convenience helper on JSString::SafeString since that
made it possible to casually turn the return value from JSString::view() into an unsafe
StringView local on the stack with this pattern:

StringView view = someJSValue.toString(exec)->view(exec);

The JSString* returned by toString() above will go out of scope by the end of the statement
and does not stick around to protect itself from garbage collection.

It will now look like this instead:

JSString::SafeView view = someJSValue.toString(exec)->view(exec);

To be extra clear, the following is not safe:

StringView view = someJSValue.toString(exec)->view(exec).get();

By the end of that statement, the JSString::SafeView goes out of scope, and the JSString*
is no longer protected from GC.

I added a couple of forwarding helpers to the SafeView class, and if you need a StringView
object from it, you can call .get() just like before.

Finally I also removed the JSString::SafeView() constructor, since nobody was instantiating
empty SafeView objects anyway. This way we don't have to worry about null members.

  • runtime/ArrayPrototype.cpp:

(JSC::arrayProtoFuncJoin):

  • runtime/FunctionConstructor.cpp:

(JSC::constructFunctionSkippingEvalEnabledCheck):

  • runtime/JSGenericTypedArrayViewPrototypeFunctions.h:

(JSC::genericTypedArrayViewProtoFuncJoin):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::decode):
(JSC::globalFuncParseInt):
(JSC::globalFuncParseFloat):
(JSC::globalFuncEscape):
(JSC::globalFuncUnescape):

  • runtime/JSONObject.cpp:

(JSC::JSONProtoFuncParse):

  • runtime/JSString.cpp:

(JSC::JSString::getPrimitiveNumber):
(JSC::JSString::toNumber):

  • runtime/JSString.h:

(JSC::JSString::SafeView::is8Bit):
(JSC::JSString::SafeView::length):
(JSC::JSString::SafeView::characters8):
(JSC::JSString::SafeView::characters16):
(JSC::JSString::SafeView::operator[]):
(JSC::JSString::SafeView::SafeView):
(JSC::JSString::SafeView::get):
(JSC::JSString::SafeView::operator StringView): Deleted.

  • runtime/StringPrototype.cpp:

(JSC::stringProtoFuncCharAt):
(JSC::stringProtoFuncCharCodeAt):
(JSC::stringProtoFuncIndexOf):
(JSC::stringProtoFuncNormalize):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSString.h

    r190601 r194310  
    433433class JSString::SafeView {
    434434public:
    435     SafeView();
    436435    explicit SafeView(ExecState&, const JSString&);
    437     operator StringView() const;
    438436    StringView get() const;
    439437
     438    bool is8Bit() const { return m_string->is8Bit(); }
     439    unsigned length() const { return m_string->length(); }
     440    const LChar* characters8() const { return get().characters8(); }
     441    const UChar* characters16() const { return get().characters16(); }
     442    UChar operator[](unsigned index) const { return get()[index]; }
     443
    440444private:
    441     ExecState* m_state { nullptr };
     445    ExecState& m_state;
    442446
    443447    // The following pointer is marked "volatile" to make the compiler leave it on the stack
     
    445449    // That's needed to prevent garbage collecting the string and possibly deleting the block
    446450    // with the characters in it, and then using the StringView after that.
    447     const JSString* volatile m_string { nullptr };
     451    const JSString* volatile m_string;
    448452};
    449453
     
    708712}
    709713
    710 inline JSString::SafeView::SafeView()
    711 {
    712 }
    713 
    714714inline JSString::SafeView::SafeView(ExecState& state, const JSString& string)
    715     : m_state(&state)
     715    : m_state(state)
    716716    , m_string(&string)
    717717{
    718718}
    719719
    720 inline JSString::SafeView::operator StringView() const
    721 {
    722     return m_string->unsafeView(*m_state);
    723 }
    724 
    725720inline StringView JSString::SafeView::get() const
    726721{
    727     return *this;
     722    return m_string->unsafeView(m_state);
    728723}
    729724
Note: See TracChangeset for help on using the changeset viewer.