Everywhere: Fix incorrect usages of AK::Checked
Specifically, explicitly specify the checked type, use the resulting value instead of doing the same calculation twice, and break down calculations to discrete operations to ensure no intermediary overflows are missed.
This commit is contained in:
parent
3f70efed9c
commit
301c1a3a58
Notes:
sideshowbarker
2024-07-18 10:27:40 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/301c1a3a58c Pull-request: https://github.com/SerenityOS/serenity/pull/8438
6 changed files with 16 additions and 15 deletions
|
@ -131,42 +131,42 @@ template<typename T>
|
|||
[[nodiscard]] inline bool copy_n_from_user(T* dest, const T* src, size_t count)
|
||||
{
|
||||
static_assert(IsTriviallyCopyable<T>);
|
||||
Checked size = sizeof(T);
|
||||
Checked<size_t> size = sizeof(T);
|
||||
size *= count;
|
||||
if (size.has_overflow())
|
||||
return false;
|
||||
return copy_from_user(dest, src, sizeof(T) * count);
|
||||
return copy_from_user(dest, src, size.value());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] inline bool copy_n_to_user(T* dest, const T* src, size_t count)
|
||||
{
|
||||
static_assert(IsTriviallyCopyable<T>);
|
||||
Checked size = sizeof(T);
|
||||
Checked<size_t> size = sizeof(T);
|
||||
size *= count;
|
||||
if (size.has_overflow())
|
||||
return false;
|
||||
return copy_to_user(dest, src, sizeof(T) * count);
|
||||
return copy_to_user(dest, src, size.value());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] inline bool copy_n_from_user(T* dest, Userspace<const T*> src, size_t count)
|
||||
{
|
||||
static_assert(IsTriviallyCopyable<T>);
|
||||
Checked size = sizeof(T);
|
||||
Checked<size_t> size = sizeof(T);
|
||||
size *= count;
|
||||
if (size.has_overflow())
|
||||
return false;
|
||||
return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T) * count);
|
||||
return copy_from_user(dest, src.unsafe_userspace_ptr(), size.value());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] inline bool copy_n_to_user(Userspace<T*> dest, const T* src, size_t count)
|
||||
{
|
||||
static_assert(IsTriviallyCopyable<T>);
|
||||
Checked size = sizeof(T);
|
||||
Checked<size_t> size = sizeof(T);
|
||||
size *= count;
|
||||
if (size.has_overflow())
|
||||
return false;
|
||||
return copy_to_user(dest.unsafe_userspace_ptr(), src, sizeof(T) * count);
|
||||
return copy_to_user(dest.unsafe_userspace_ptr(), src, size.value());
|
||||
}
|
||||
|
|
|
@ -942,14 +942,14 @@ KResultOr<FlatPtr> Process::sys$execve(Userspace<const Syscall::SC_execve_params
|
|||
auto copy_user_strings = [](const auto& list, auto& output) {
|
||||
if (!list.length)
|
||||
return true;
|
||||
Checked size = sizeof(*list.strings);
|
||||
Checked<size_t> size = sizeof(*list.strings);
|
||||
size *= list.length;
|
||||
if (size.has_overflow())
|
||||
return false;
|
||||
Vector<Syscall::StringArgument, 32> strings;
|
||||
if (!strings.try_resize(list.length))
|
||||
return false;
|
||||
if (!copy_from_user(strings.data(), list.strings, list.length * sizeof(*list.strings)))
|
||||
if (!copy_from_user(strings.data(), list.strings, size.value()))
|
||||
return false;
|
||||
for (size_t i = 0; i < list.length; ++i) {
|
||||
auto string = copy_string_from_user(strings[i]);
|
||||
|
|
|
@ -152,7 +152,7 @@ KResultOr<FlatPtr> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> u
|
|||
|
||||
Vector<pollfd, FD_SETSIZE> fds_copy;
|
||||
if (params.nfds > 0) {
|
||||
Checked nfds_checked = sizeof(pollfd);
|
||||
Checked<size_t> nfds_checked = sizeof(pollfd);
|
||||
nfds_checked *= params.nfds;
|
||||
if (nfds_checked.has_overflow())
|
||||
return EFAULT;
|
||||
|
|
|
@ -97,7 +97,8 @@ static void initialize_typed_array_from_typed_array(GlobalObject& global_object,
|
|||
|
||||
auto element_length = src_array.array_length();
|
||||
auto element_size = dest_array.element_size();
|
||||
Checked byte_length = element_size * element_length;
|
||||
Checked<size_t> byte_length = element_size;
|
||||
byte_length *= element_length;
|
||||
if (byte_length.has_overflow()) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::InvalidLength, "typed array");
|
||||
return;
|
||||
|
|
|
@ -362,7 +362,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::set)
|
|||
return {};
|
||||
}
|
||||
|
||||
Checked checked { source_length };
|
||||
Checked<size_t> checked = source_length;
|
||||
checked += static_cast<u32>(target_offset);
|
||||
if (checked.has_overflow() || checked.value() > target_length) {
|
||||
vm.throw_exception<JS::RangeError>(global_object, "Overflow or out of bounds in target length");
|
||||
|
@ -436,7 +436,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::set)
|
|||
return {};
|
||||
}
|
||||
|
||||
Checked checked { source_length };
|
||||
Checked<size_t> checked = source_length;
|
||||
checked += static_cast<u32>(target_offset);
|
||||
if (checked.has_overflow() || checked.value() > target_length) {
|
||||
vm.throw_exception<JS::RangeError>(global_object, "Overflow or out of bounds in target length");
|
||||
|
|
|
@ -191,7 +191,7 @@ void BytecodeInterpreter::call_address(Configuration& configuration, FunctionAdd
|
|||
TRAP_IF_NOT(rhs.has_value()); \
|
||||
dbgln_if(WASM_TRACE_DEBUG, "{} {} {} = ??", ulhs.value(), #operator, rhs.value()); \
|
||||
__VA_ARGS__; \
|
||||
Checked lhs = ulhs.value(); \
|
||||
Checked<type> lhs = ulhs.value(); \
|
||||
lhs operator##= rhs.value(); \
|
||||
TRAP_IF_NOT(!lhs.has_overflow()); \
|
||||
auto result = lhs.value(); \
|
||||
|
|
Loading…
Add table
Reference in a new issue