LibWeb: Fix stack-use-after-scope

The refactor in the previous commit was storing a reference to a stack
allocated `Infrastructure::Request::BodyType` which was then immediately
freed. To fix this, we can store the `Infrastructure::Request::BodyType`
in a variable beforehand, so it becomes safe to reference.
This commit is contained in:
Jonne Ransijn 2024-11-26 18:17:44 +01:00 committed by Ali Mohammad Pur
commit 211dc5659c
Notes: github-actions[bot] 2024-12-04 00:59:15 +00:00
2 changed files with 9 additions and 8 deletions

View file

@ -71,14 +71,17 @@ public:
return static_cast<Self const&>(*this).has_value() ? __builtin_launder(reinterpret_cast<T const*>(&static_cast<Self const&>(*this).value())) : nullptr; return static_cast<Self const&>(*this).has_value() ? __builtin_launder(reinterpret_cast<T const*>(&static_cast<Self const&>(*this).value())) : nullptr;
} }
[[nodiscard]] ALWAYS_INLINE T value_or(T const& fallback) const& template<typename O = T, typename Fallback = O>
[[nodiscard]] ALWAYS_INLINE O value_or(Fallback const& fallback) const&
{ {
if (static_cast<Self const&>(*this).has_value()) if (static_cast<Self const&>(*this).has_value())
return static_cast<Self const&>(*this).value(); return static_cast<Self const&>(*this).value();
return fallback; return fallback;
} }
[[nodiscard]] ALWAYS_INLINE T value_or(T&& fallback) && template<typename O = T, typename Fallback = O>
requires(!IsLvalueReference<O> && !IsRvalueReference<O>)
[[nodiscard]] ALWAYS_INLINE O value_or(Fallback&& fallback) &&
{ {
if (static_cast<Self&>(*this).has_value()) if (static_cast<Self&>(*this).has_value())
return move(static_cast<Self&>(*this).value()); return move(static_cast<Self&>(*this).value());

View file

@ -448,7 +448,7 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Method must not be GET or HEAD when body is provided"sv }; return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Method must not be GET or HEAD when body is provided"sv };
// 36. Let initBody be null. // 36. Let initBody be null.
GC::Ptr<Infrastructure::Body> init_body; Optional<Infrastructure::Request::BodyType> init_body;
// 37. If init["body"] exists and is non-null, then: // 37. If init["body"] exists and is non-null, then:
if (init.body.has_value() && (*init.body).has_value()) { if (init.body.has_value() && (*init.body).has_value()) {
@ -467,15 +467,13 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
} }
// 38. Let inputOrInitBody be initBody if it is non-null; otherwise inputBody. // 38. Let inputOrInitBody be initBody if it is non-null; otherwise inputBody.
Optional<Infrastructure::Request::BodyType const&> input_or_init_body = init_body auto input_or_init_body = init_body.value_or<Optional<Infrastructure::Request::BodyType const&>>(input_body);
? Infrastructure::Request::BodyType { *init_body }
: input_body;
// 39. If inputOrInitBody is non-null and inputOrInitBodys source is null, then: // 39. If inputOrInitBody is non-null and inputOrInitBodys source is null, then:
// FIXME: The spec doesn't check if inputOrInitBody is a body before accessing source. // FIXME: The spec doesn't check if inputOrInitBody is a body before accessing source.
if (input_or_init_body.has_value() && input_or_init_body->has<GC::Ref<Infrastructure::Body>>() && input_or_init_body->get<GC::Ref<Infrastructure::Body>>()->source().has<Empty>()) { if (input_or_init_body.has_value() && input_or_init_body->has<GC::Ref<Infrastructure::Body>>() && input_or_init_body->get<GC::Ref<Infrastructure::Body>>()->source().has<Empty>()) {
// 1. If initBody is non-null and init["duplex"] does not exist, then throw a TypeError. // 1. If initBody is non-null and init["duplex"] does not exist, then throw a TypeError.
if (init_body && !init.duplex.has_value()) if (init_body.has_value() && !init.duplex.has_value())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Body without source requires 'duplex' value to be set"sv }; return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Body without source requires 'duplex' value to be set"sv };
// 2. If thiss requests mode is neither "same-origin" nor "cors", then throw a TypeError. // 2. If thiss requests mode is neither "same-origin" nor "cors", then throw a TypeError.
@ -490,7 +488,7 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
auto const& final_body = input_or_init_body; auto const& final_body = input_or_init_body;
// 41. If initBody is null and inputBody is non-null, then: // 41. If initBody is null and inputBody is non-null, then:
if (!init_body && input_body.has_value()) { if (!init_body.has_value() && input_body.has_value()) {
// 2. If input is unusable, then throw a TypeError. // 2. If input is unusable, then throw a TypeError.
if (input.has<GC::Root<Request>>() && input.get<GC::Root<Request>>()->is_unusable()) if (input.has<GC::Root<Request>>() && input.get<GC::Root<Request>>()->is_unusable())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Request is unusable"sv }; return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Request is unusable"sv };