From 4dfb99fcb2f4e9ff9e4bfef8df891035a65da8c9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 18 Apr 2024 16:14:46 +0200 Subject: [PATCH] QRestReply: allow comments where white-space is allowed This is RFC2822 grammar (except that line folding is not allowed). RFC9110 doesn't allow it anymore, but it might make sense to accept it nonetheless (Postel's Law). Manual conflict resolutions: - dropped constexpr on parse_comment(), which uses QByteArrayView's startsWith(char), which is only constexpr in 6.8. Task-number: QTBUG-123544 Change-Id: Ie990cd332c7603dbdae29c19b2804bd33a058ca0 Reviewed-by: Juha Vuolle (cherry picked from commit 834e7d60a9cb67a1d445151a4f7c34d4288db01b) --- src/network/access/qrestreply.cpp | 64 ++++++++++++++++--- .../tst_qrestaccessmanager.cpp | 2 +- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/network/access/qrestreply.cpp b/src/network/access/qrestreply.cpp index 2fe674227d9..e473c032128 100644 --- a/src/network/access/qrestreply.cpp +++ b/src/network/access/qrestreply.cpp @@ -420,6 +420,54 @@ static constexpr bool is_tchar(char ch) noexcept } } +static auto parse_comment(QByteArrayView data) noexcept +{ + struct R { + QByteArrayView comment, tail; + constexpr explicit operator bool() const noexcept { return !comment.isEmpty(); } + }; + + const auto invalid = R{{}, data}; // preserves original `data` + + // comment = "(" *( ctext / quoted-pair / comment ) ")" + // ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text + + if (!data.startsWith('(')) + return invalid; + + qsizetype i = 1; + qsizetype level = 1; + while (i < data.size()) { + switch (data[i++]) { + case '(': // nested comment + ++level; + break; + case ')': // end of comment + if (--level == 0) + return R{data.first(i), data.sliced(i)}; + break; + case '\\': // quoted-pair + if (i == data.size()) + return invalid; // premature end + ++i; // eat escaped character + break; + default: + ; // don't validate ctext - accept everything (Postel's Law) + } + } + + return invalid; // premature end / unbalanced nesting levels +} + +static void eat_CWS(QByteArrayView &data) noexcept +{ + eat_OWS(data); + while (const auto comment = parse_comment(data)) { + data = comment.tail; + eat_OWS(data); + } +} + static constexpr auto parse_token(QByteArrayView data) noexcept { struct R { @@ -452,13 +500,13 @@ static auto parse_parameter(QByteArrayView data, qxp::function_ref