AK: Disallow calling ByteString methods that return a view on rvalues

This prevents, for example:

    StringView view = ByteString { "foo" }.view();

This prevents a class of potential UAF.
This commit is contained in:
Timothy Flynn 2024-04-03 22:01:43 -04:00 committed by Andreas Kling
parent de80f544d8
commit c5c5e52c24
2 changed files with 22 additions and 17 deletions

View file

@ -81,14 +81,14 @@ ByteString ByteString::substring(size_t start) const
return { characters() + start, length() - start };
}
StringView ByteString::substring_view(size_t start, size_t length) const
StringView ByteString::substring_view(size_t start, size_t length) const&
{
VERIFY(!Checked<size_t>::addition_would_overflow(start, length));
VERIFY(start + length <= m_impl->length());
return { characters() + start, length };
}
StringView ByteString::substring_view(size_t start) const
StringView ByteString::substring_view(size_t start) const&
{
VERIFY(start <= length());
return { characters() + start, length() - start };
@ -123,7 +123,7 @@ Vector<ByteString> ByteString::split_limit(char separator, size_t limit, SplitBe
return v;
}
Vector<StringView> ByteString::split_view(Function<bool(char)> separator, SplitBehavior split_behavior) const
Vector<StringView> ByteString::split_view(Function<bool(char)> separator, SplitBehavior split_behavior) const&
{
if (is_empty())
return {};
@ -147,7 +147,7 @@ Vector<StringView> ByteString::split_view(Function<bool(char)> separator, SplitB
return v;
}
Vector<StringView> ByteString::split_view(char const separator, SplitBehavior split_behavior) const
Vector<StringView> ByteString::split_view(char const separator, SplitBehavior split_behavior) const&
{
return split_view([separator](char ch) { return ch == separator; }, split_behavior);
}

View file

@ -166,8 +166,12 @@ public:
[[nodiscard]] Vector<ByteString> split_limit(char separator, size_t limit, SplitBehavior = SplitBehavior::Nothing) const;
[[nodiscard]] Vector<ByteString> split(char separator, SplitBehavior = SplitBehavior::Nothing) const;
[[nodiscard]] Vector<StringView> split_view(char separator, SplitBehavior = SplitBehavior::Nothing) const;
[[nodiscard]] Vector<StringView> split_view(Function<bool(char)> separator, SplitBehavior = SplitBehavior::Nothing) const;
[[nodiscard]] Vector<StringView> split_view(char separator, SplitBehavior = SplitBehavior::Nothing) const&;
[[nodiscard]] Vector<StringView> split_view(char separator, SplitBehavior = SplitBehavior::Nothing) const&& = delete;
[[nodiscard]] Vector<StringView> split_view(Function<bool(char)> separator, SplitBehavior = SplitBehavior::Nothing) const&;
[[nodiscard]] Vector<StringView> split_view(Function<bool(char)> separator, SplitBehavior = SplitBehavior::Nothing) const&& = delete;
[[nodiscard]] Optional<size_t> find(char needle, size_t start = 0) const { return StringUtils::find(*this, needle, start); }
[[nodiscard]] Optional<size_t> find(StringView needle, size_t start = 0) const { return StringUtils::find(*this, needle, start); }
@ -177,12 +181,17 @@ public:
using SearchDirection = StringUtils::SearchDirection;
[[nodiscard]] Optional<size_t> find_any_of(StringView needles, SearchDirection direction) const { return StringUtils::find_any_of(*this, needles, direction); }
[[nodiscard]] StringView find_last_split_view(char separator) const { return view().find_last_split_view(separator); }
[[nodiscard]] StringView find_last_split_view(char separator) const& { return view().find_last_split_view(separator); }
[[nodiscard]] StringView find_last_split_view(char separator) const&& = delete;
[[nodiscard]] ByteString substring(size_t start, size_t length) const;
[[nodiscard]] ByteString substring(size_t start) const;
[[nodiscard]] StringView substring_view(size_t start, size_t length) const;
[[nodiscard]] StringView substring_view(size_t start) const;
[[nodiscard]] StringView substring_view(size_t start, size_t length) const&;
[[nodiscard]] StringView substring_view(size_t start, size_t length) const&& = delete;
[[nodiscard]] StringView substring_view(size_t start) const&;
[[nodiscard]] StringView substring_view(size_t start) const&& = delete;
[[nodiscard]] ALWAYS_INLINE bool is_empty() const { return length() == 0; }
[[nodiscard]] ALWAYS_INLINE size_t length() const { return m_impl->length(); }
@ -191,10 +200,8 @@ public:
[[nodiscard]] bool copy_characters_to_buffer(char* buffer, size_t buffer_size) const;
[[nodiscard]] ALWAYS_INLINE ReadonlyBytes bytes() const
{
return m_impl->bytes();
}
[[nodiscard]] ALWAYS_INLINE ReadonlyBytes bytes() const& { return m_impl->bytes(); }
[[nodiscard]] ALWAYS_INLINE ReadonlyBytes bytes() const&& = delete;
[[nodiscard]] ALWAYS_INLINE char const& operator[](size_t i) const
{
@ -292,10 +299,8 @@ public:
return formatted("{}", value);
}
[[nodiscard]] StringView view() const
{
return { characters(), length() };
}
[[nodiscard]] StringView view() const& { return { characters(), length() }; }
[[nodiscard]] StringView view() const&& = delete;
[[nodiscard]] ByteString replace(StringView needle, StringView replacement, ReplaceMode replace_mode = ReplaceMode::All) const { return StringUtils::replace(*this, needle, replacement, replace_mode); }
[[nodiscard]] size_t count(StringView needle) const { return StringUtils::count(*this, needle); }