1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 09:24:57 +00:00

LibGemini: Disallow cases forbidden in the spec

The gemini spec at <https://gemini.circumlunar.space/docs/specification.gmi>
does not allow status lines and meta messages to start with a byte order
mark. It also forbids meta messages longer than 1024 bytes.
This commit is contained in:
Arda Cinar 2023-01-13 20:45:14 +03:00 committed by Andreas Kling
parent ba9fa59355
commit 93c1fb0b76

View file

@ -7,6 +7,7 @@
#include <AK/Debug.h>
#include <AK/Error.h>
#include <AK/String.h>
#include <AK/Utf8View.h>
#include <LibCore/Stream.h>
#include <LibGemini/GeminiResponse.h>
#include <LibGemini/Job.h>
@ -127,6 +128,8 @@ void Job::on_socket_connected()
if (m_state == State::Failed)
return;
// https://gemini.circumlunar.space/docs/specification.gmi
if (m_state == State::InStatus) {
if (!can_read_line())
return;
@ -141,6 +144,19 @@ void Job::on_socket_connected()
auto line = line_or_error.release_value();
auto view = line.bytes_as_string_view();
auto first_code_point = line.code_points().begin().peek();
if (!first_code_point.has_value()) {
dbgln("Job: empty status line");
m_state = State::Failed;
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
}
if (first_code_point.release_value() == 0xFEFF) {
dbgln("Job: Byte order mark as first character of status line");
m_state = State::Failed;
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
}
auto maybe_space_index = view.find(' ');
if (!maybe_space_index.has_value()) {
dbgln("Job: Expected 2-part status line, got '{}'", line);
@ -159,6 +175,19 @@ void Job::on_socket_connected()
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
}
auto meta_first_code_point = Utf8View(second_part).begin().peek();
if (meta_first_code_point.release_value() == 0xFEFF) {
dbgln("Job: Byte order mark as first character of meta");
m_state = State::Failed;
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
}
if (second_part.length() > 1024) {
dbgln("Job: Meta too long");
m_state = State::Failed;
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
}
m_status = status.release_value();
m_meta = second_part;