mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 13:36:13 +03:00
AK: Disallow returning of string literals for errors in kernel code
This code should not be used in the kernel - we should always propagate proper errno codes in case we need to return those to userland so it could decode it in a reasonable way.
This commit is contained in:
parent
56b799c556
commit
048fb2c204
Notes:
sideshowbarker
2024-07-17 04:34:25 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/048fb2c204 Pull-request: https://github.com/SerenityOS/serenity/pull/17308 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/linusg
33
AK/Error.h
33
AK/Error.h
@ -31,7 +31,12 @@ public:
|
|||||||
// For calling this method from userspace programs, we will simply return from
|
// For calling this method from userspace programs, we will simply return from
|
||||||
// the Error::from_string_view method!
|
// the Error::from_string_view method!
|
||||||
[[nodiscard]] static Error from_string_view_or_print_error_and_return_errno(StringView string_literal, int code);
|
[[nodiscard]] static Error from_string_view_or_print_error_and_return_errno(StringView string_literal, int code);
|
||||||
[[nodiscard]] static Error from_syscall(StringView syscall_name, int rc) { return Error(syscall_name, rc); }
|
|
||||||
|
#ifndef KERNEL
|
||||||
|
[[nodiscard]] static Error from_syscall(StringView syscall_name, int rc)
|
||||||
|
{
|
||||||
|
return Error(syscall_name, rc);
|
||||||
|
}
|
||||||
[[nodiscard]] static Error from_string_view(StringView string_literal) { return Error(string_literal); }
|
[[nodiscard]] static Error from_string_view(StringView string_literal) { return Error(string_literal); }
|
||||||
|
|
||||||
[[nodiscard]] static Error copy(Error const& error)
|
[[nodiscard]] static Error copy(Error const& error)
|
||||||
@ -57,17 +62,29 @@ public:
|
|||||||
{
|
{
|
||||||
return from_string_view(string);
|
return from_string_view(string);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool operator==(Error const& other) const
|
bool operator==(Error const& other) const
|
||||||
{
|
{
|
||||||
|
#ifdef KERNEL
|
||||||
|
return m_code == other.m_code;
|
||||||
|
#else
|
||||||
return m_code == other.m_code && m_string_literal == other.m_string_literal && m_syscall == other.m_syscall;
|
return m_code == other.m_code && m_string_literal == other.m_string_literal && m_syscall == other.m_syscall;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_errno() const { return m_code != 0; }
|
|
||||||
bool is_syscall() const { return m_syscall; }
|
|
||||||
|
|
||||||
int code() const { return m_code; }
|
int code() const { return m_code; }
|
||||||
StringView string_literal() const { return m_string_literal; }
|
#ifndef KERNEL
|
||||||
|
bool is_errno() const
|
||||||
|
{
|
||||||
|
return m_code != 0;
|
||||||
|
}
|
||||||
|
bool is_syscall() const { return m_syscall; }
|
||||||
|
StringView string_literal() const
|
||||||
|
{
|
||||||
|
return m_string_literal;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Error(int code)
|
Error(int code)
|
||||||
@ -76,6 +93,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#ifndef KERNEL
|
||||||
Error(StringView string_literal)
|
Error(StringView string_literal)
|
||||||
: m_string_literal(string_literal)
|
: m_string_literal(string_literal)
|
||||||
{
|
{
|
||||||
@ -92,8 +110,13 @@ private:
|
|||||||
Error& operator=(Error const&) = default;
|
Error& operator=(Error const&) = default;
|
||||||
|
|
||||||
StringView m_string_literal;
|
StringView m_string_literal;
|
||||||
|
#endif
|
||||||
|
|
||||||
int m_code { 0 };
|
int m_code { 0 };
|
||||||
|
|
||||||
|
#ifndef KERNEL
|
||||||
bool m_syscall { false };
|
bool m_syscall { false };
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename E>
|
template<typename T, typename E>
|
||||||
|
@ -684,9 +684,7 @@ struct Formatter<Error> : Formatter<FormatString> {
|
|||||||
ErrorOr<void> format(FormatBuilder& builder, Error const& error)
|
ErrorOr<void> format(FormatBuilder& builder, Error const& error)
|
||||||
{
|
{
|
||||||
#if defined(AK_OS_SERENITY) && defined(KERNEL)
|
#if defined(AK_OS_SERENITY) && defined(KERNEL)
|
||||||
if (error.is_errno())
|
return Formatter<FormatString>::format(builder, "Error(errno={})"sv, error.code());
|
||||||
return Formatter<FormatString>::format(builder, "Error(errno={})"sv, error.code());
|
|
||||||
return Formatter<FormatString>::format(builder, "Error({})"sv, error.string_literal());
|
|
||||||
#else
|
#else
|
||||||
if (error.is_syscall())
|
if (error.is_syscall())
|
||||||
return Formatter<FormatString>::format(builder, "{}: {} (errno={})"sv, error.string_literal(), strerror(error.code()), error.code());
|
return Formatter<FormatString>::format(builder, "{}: {} (errno={})"sv, error.string_literal(), strerror(error.code()), error.code());
|
||||||
|
@ -15,18 +15,18 @@ namespace AK {
|
|||||||
ErrorOr<ByteBuffer> decode_hex(StringView input)
|
ErrorOr<ByteBuffer> decode_hex(StringView input)
|
||||||
{
|
{
|
||||||
if ((input.length() % 2) != 0)
|
if ((input.length() % 2) != 0)
|
||||||
return Error::from_string_literal("Hex string was not an even length");
|
return Error::from_string_view_or_print_error_and_return_errno("Hex string was not an even length"sv, EINVAL);
|
||||||
|
|
||||||
auto output = TRY(ByteBuffer::create_zeroed(input.length() / 2));
|
auto output = TRY(ByteBuffer::create_zeroed(input.length() / 2));
|
||||||
|
|
||||||
for (size_t i = 0; i < input.length() / 2; ++i) {
|
for (size_t i = 0; i < input.length() / 2; ++i) {
|
||||||
auto const c1 = decode_hex_digit(input[i * 2]);
|
auto const c1 = decode_hex_digit(input[i * 2]);
|
||||||
if (c1 >= 16)
|
if (c1 >= 16)
|
||||||
return Error::from_string_literal("Hex string contains invalid digit");
|
return Error::from_string_view_or_print_error_and_return_errno("Hex string contains invalid digit"sv, EINVAL);
|
||||||
|
|
||||||
auto const c2 = decode_hex_digit(input[i * 2 + 1]);
|
auto const c2 = decode_hex_digit(input[i * 2 + 1]);
|
||||||
if (c2 >= 16)
|
if (c2 >= 16)
|
||||||
return Error::from_string_literal("Hex string contains invalid digit");
|
return Error::from_string_view_or_print_error_and_return_errno("Hex string contains invalid digit"sv, EINVAL);
|
||||||
|
|
||||||
output[i] = (c1 << 4) + c2;
|
output[i] = (c1 << 4) + c2;
|
||||||
}
|
}
|
||||||
|
@ -59,19 +59,19 @@ ErrorOr<size_t> FixedMemoryStream::seek(i64 offset, SeekMode seek_mode)
|
|||||||
switch (seek_mode) {
|
switch (seek_mode) {
|
||||||
case SeekMode::SetPosition:
|
case SeekMode::SetPosition:
|
||||||
if (offset > static_cast<i64>(m_bytes.size()))
|
if (offset > static_cast<i64>(m_bytes.size()))
|
||||||
return Error::from_string_literal("Offset past the end of the stream memory");
|
return Error::from_string_view_or_print_error_and_return_errno("Offset past the end of the stream memory"sv, EINVAL);
|
||||||
|
|
||||||
m_offset = offset;
|
m_offset = offset;
|
||||||
break;
|
break;
|
||||||
case SeekMode::FromCurrentPosition:
|
case SeekMode::FromCurrentPosition:
|
||||||
if (offset + static_cast<i64>(m_offset) > static_cast<i64>(m_bytes.size()))
|
if (offset + static_cast<i64>(m_offset) > static_cast<i64>(m_bytes.size()))
|
||||||
return Error::from_string_literal("Offset past the end of the stream memory");
|
return Error::from_string_view_or_print_error_and_return_errno("Offset past the end of the stream memory"sv, EINVAL);
|
||||||
|
|
||||||
m_offset += offset;
|
m_offset += offset;
|
||||||
break;
|
break;
|
||||||
case SeekMode::FromEndPosition:
|
case SeekMode::FromEndPosition:
|
||||||
if (offset > static_cast<i64>(m_bytes.size()))
|
if (offset > static_cast<i64>(m_bytes.size()))
|
||||||
return Error::from_string_literal("Offset past the start of the stream memory");
|
return Error::from_string_view_or_print_error_and_return_errno("Offset past the start of the stream memory"sv, EINVAL);
|
||||||
|
|
||||||
m_offset = m_bytes.size() - offset;
|
m_offset = m_bytes.size() - offset;
|
||||||
break;
|
break;
|
||||||
@ -92,7 +92,7 @@ ErrorOr<size_t> FixedMemoryStream::write(ReadonlyBytes bytes)
|
|||||||
ErrorOr<void> FixedMemoryStream::write_entire_buffer(ReadonlyBytes bytes)
|
ErrorOr<void> FixedMemoryStream::write_entire_buffer(ReadonlyBytes bytes)
|
||||||
{
|
{
|
||||||
if (remaining() < bytes.size())
|
if (remaining() < bytes.size())
|
||||||
return Error::from_string_literal("Write of entire buffer ends past the memory area");
|
return Error::from_string_view_or_print_error_and_return_errno("Write of entire buffer ends past the memory area"sv, EINVAL);
|
||||||
|
|
||||||
TRY(write(bytes));
|
TRY(write(bytes));
|
||||||
return {};
|
return {};
|
||||||
@ -163,7 +163,7 @@ ErrorOr<void> AllocatingMemoryStream::discard(size_t count)
|
|||||||
VERIFY(m_write_offset >= m_read_offset);
|
VERIFY(m_write_offset >= m_read_offset);
|
||||||
|
|
||||||
if (count > used_buffer_size())
|
if (count > used_buffer_size())
|
||||||
return Error::from_string_literal("Number of discarded bytes is higher than the number of allocated bytes");
|
return Error::from_string_view_or_print_error_and_return_errno("Number of discarded bytes is higher than the number of allocated bytes"sv, EINVAL);
|
||||||
|
|
||||||
m_read_offset += count;
|
m_read_offset += count;
|
||||||
|
|
||||||
|
@ -16,14 +16,19 @@ ErrorOr<void> Stream::read_entire_buffer(Bytes buffer)
|
|||||||
size_t nread = 0;
|
size_t nread = 0;
|
||||||
while (nread < buffer.size()) {
|
while (nread < buffer.size()) {
|
||||||
if (is_eof())
|
if (is_eof())
|
||||||
return Error::from_string_literal("Reached end-of-file before filling the entire buffer");
|
return Error::from_string_view_or_print_error_and_return_errno("Reached end-of-file before filling the entire buffer"sv, EIO);
|
||||||
|
|
||||||
auto result = read(buffer.slice(nread));
|
auto result = read(buffer.slice(nread));
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
|
#ifdef KERNEL
|
||||||
|
if (result.error().code() == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (result.error().is_errno() && result.error().code() == EINTR) {
|
if (result.error().is_errno() && result.error().code() == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return result.release_error();
|
return result.release_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +74,7 @@ ErrorOr<void> Stream::discard(size_t discarded_bytes)
|
|||||||
|
|
||||||
while (discarded_bytes > 0) {
|
while (discarded_bytes > 0) {
|
||||||
if (is_eof())
|
if (is_eof())
|
||||||
return Error::from_string_literal("Reached end-of-file before reading all discarded bytes");
|
return Error::from_string_view_or_print_error_and_return_errno("Reached end-of-file before reading all discarded bytes"sv, EIO);
|
||||||
|
|
||||||
auto slice = TRY(read(buffer.span().slice(0, min(discarded_bytes, continuous_read_size))));
|
auto slice = TRY(read(buffer.span().slice(0, min(discarded_bytes, continuous_read_size))));
|
||||||
discarded_bytes -= slice.size();
|
discarded_bytes -= slice.size();
|
||||||
@ -84,10 +89,15 @@ ErrorOr<void> Stream::write_entire_buffer(ReadonlyBytes buffer)
|
|||||||
while (nwritten < buffer.size()) {
|
while (nwritten < buffer.size()) {
|
||||||
auto result = write(buffer.slice(nwritten));
|
auto result = write(buffer.slice(nwritten));
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
|
#ifdef KERNEL
|
||||||
|
if (result.error().code() == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (result.error().is_errno() && result.error().code() == EINTR) {
|
if (result.error().is_errno() && result.error().code() == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return result.release_error();
|
return result.release_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user