From 55e6e6f1170f1c59ccc965d36bdd3a692dd0aa9f Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Wed, 10 Dec 2025 10:32:02 +0100 Subject: [PATCH] Everywhere: Make `ByteBuffer::bytes()` lvalue-only This helps prevent us from accidentally using pointers to the underlying memory of temporary `ByteBuffer` values. --- AK/ByteBuffer.h | 13 +++++++++---- Libraries/LibRequests/RequestClient.cpp | 7 ++++--- Libraries/LibRequests/WebSocket.cpp | 2 +- Libraries/LibWeb/Compression/CompressionStream.cpp | 2 +- Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp | 4 ++-- Tests/LibTLS/TestTLSHandshake.cpp | 3 ++- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/AK/ByteBuffer.h b/AK/ByteBuffer.h index aedae59872..9e8a14e87f 100644 --- a/AK/ByteBuffer.h +++ b/AK/ByteBuffer.h @@ -147,11 +147,14 @@ public: # pragma GCC diagnostic pop #endif - [[nodiscard]] Bytes bytes() LIFETIME_BOUND + [[nodiscard]] Bytes bytes() && LIFETIME_BOUND = delete; + [[nodiscard]] Bytes bytes() & LIFETIME_BOUND { return { data(), size() }; } - [[nodiscard]] ReadonlyBytes bytes() const LIFETIME_BOUND { return { data(), size() }; } + + [[nodiscard]] ReadonlyBytes bytes() const&& = delete; + [[nodiscard]] ReadonlyBytes bytes() const& LIFETIME_BOUND { return { data(), size() }; } [[nodiscard]] AK::Bytes span() LIFETIME_BOUND { return { data(), size() }; } [[nodiscard]] AK::ReadonlyBytes span() const LIFETIME_BOUND { return { data(), size() }; } @@ -306,8 +309,10 @@ public: __builtin_memset(data(), 0, m_size); } - operator Bytes() LIFETIME_BOUND { return bytes(); } - operator ReadonlyBytes() const LIFETIME_BOUND { return bytes(); } + operator Bytes() && = delete; + operator Bytes() & LIFETIME_BOUND { return bytes(); } + operator ReadonlyBytes() const&& = delete; + operator ReadonlyBytes() const& LIFETIME_BOUND { return bytes(); } ALWAYS_INLINE size_t capacity() const { return m_inline ? inline_capacity : m_outline_capacity; } ALWAYS_INLINE bool is_inline() const { return m_inline; } diff --git a/Libraries/LibRequests/RequestClient.cpp b/Libraries/LibRequests/RequestClient.cpp index b1932d7b23..413faaf6b6 100644 --- a/Libraries/LibRequests/RequestClient.cpp +++ b/Libraries/LibRequests/RequestClient.cpp @@ -39,8 +39,8 @@ void RequestClient::ensure_connection(URL::URL const& url, ::RequestServer::Cach RefPtr RequestClient::start_request(ByteString const& method, URL::URL const& url, Optional request_headers, ReadonlyBytes request_body, Core::ProxyData const& proxy_data) { - auto body_result = ByteBuffer::copy(request_body); - if (body_result.is_error()) + auto body_result_or_error = ByteBuffer::copy(request_body); + if (body_result_or_error.is_error()) return nullptr; static i32 s_next_request_id = 0; @@ -48,7 +48,8 @@ RefPtr RequestClient::start_request(ByteString const& method, URL::URL auto headers = request_headers.map([](auto const& headers) { return headers.headers().span(); }).value_or({}); - IPCProxy::async_start_request(request_id, method, url, headers, body_result.release_value(), proxy_data); + auto body_result = body_result_or_error.release_value(); + IPCProxy::async_start_request(request_id, method, url, headers, body_result, proxy_data); auto request = Request::create_from_id({}, *this, request_id); m_requests.set(request_id, request); return request; diff --git a/Libraries/LibRequests/WebSocket.cpp b/Libraries/LibRequests/WebSocket.cpp index 2001fd79de..61feb435f1 100644 --- a/Libraries/LibRequests/WebSocket.cpp +++ b/Libraries/LibRequests/WebSocket.cpp @@ -37,7 +37,7 @@ void WebSocket::set_subprotocol_in_use(ByteString subprotocol) void WebSocket::send(ByteBuffer binary_or_text_message, bool is_text) { - m_client->async_websocket_send(m_websocket_id, is_text, move(binary_or_text_message)); + m_client->async_websocket_send(m_websocket_id, is_text, binary_or_text_message); } void WebSocket::send(StringView text_message) diff --git a/Libraries/LibWeb/Compression/CompressionStream.cpp b/Libraries/LibWeb/Compression/CompressionStream.cpp index b2821a3b1d..b046acf685 100644 --- a/Libraries/LibWeb/Compression/CompressionStream.cpp +++ b/Libraries/LibWeb/Compression/CompressionStream.cpp @@ -116,7 +116,7 @@ WebIDL::ExceptionOr CompressionStream::compress_and_enqueue_chunk(JS::Valu // 2. Let buffer be the result of compressing chunk with cs's format and context. auto maybe_buffer = [&]() -> ErrorOr { auto chunk_buffer = TRY(WebIDL::get_buffer_source_copy(chunk.as_object())); - return compress(move(chunk_buffer), Finish::No); + return compress(chunk_buffer, Finish::No); }(); if (maybe_buffer.is_error()) return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to compress chunk: {}", maybe_buffer.error())) }; diff --git a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 5fcb21c843..55698f368b 100644 --- a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -4420,7 +4420,7 @@ WebIDL::ExceptionOr> ECDSA::import_key(AlgorithmParams const& // The uncompressed point format MUST be supported. // 2. If the implementation does not support the compressed point format and a compressed point is provided, throw a DataError. // 3. If a decode error occurs or an identity point is found, throw a DataError. - auto maybe_public_key = ::Crypto::PK::EC::parse_ec_key(move(key_bytes), false, {}); + auto maybe_public_key = ::Crypto::PK::EC::parse_ec_key(key_bytes, false, {}); if (maybe_public_key.is_error()) return WebIDL::DataError::create(m_realm, "Failed to parse key"_utf16); @@ -5372,7 +5372,7 @@ WebIDL::ExceptionOr> ECDH::import_key(AlgorithmParams const& // The uncompressed point format MUST be supported. // 2. If the implementation does not support the compressed point format and a compressed point is provided, throw a DataError. // 3. If a decode error occurs or an identity point is found, throw a DataError. - auto maybe_public_key = ::Crypto::PK::EC::parse_ec_key(move(key_bytes), false, {}); + auto maybe_public_key = ::Crypto::PK::EC::parse_ec_key(key_bytes, false, {}); if (maybe_public_key.is_error()) return WebIDL::DataError::create(m_realm, "Failed to parse key"_utf16); diff --git a/Tests/LibTLS/TestTLSHandshake.cpp b/Tests/LibTLS/TestTLSHandshake.cpp index 47e95323ed..f0f9d38d3c 100644 --- a/Tests/LibTLS/TestTLSHandshake.cpp +++ b/Tests/LibTLS/TestTLSHandshake.cpp @@ -49,7 +49,8 @@ TEST_CASE(test_TLS_hello_handshake) return; auto line = TRY_OR_FAIL(tls->read_until_any_of(read_buffer, Array { "\r\n"sv })); - EXPECT(line.starts_with("HTTP/1.1 204 No Content"_b)); + auto no_content_prefix = "HTTP/1.1 204 No Content"_b; + EXPECT(line.starts_with(no_content_prefix)); loop.quit(0); }; tls->set_notifications_enabled(true);