Skip to content

Commit

Permalink
Prevent alias substitution in strings
Browse files Browse the repository at this point in the history
  • Loading branch information
houmain committed Jan 16, 2024
1 parent 1e1ab17 commit 61c2661
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 26 deletions.
45 changes: 27 additions & 18 deletions src/config/ParseConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Config ParseConfig::operator()(std::istream& is) {
return std::move(m_config);
}

void ParseConfig::error(std::string message) {
void ParseConfig::error(std::string message) const {
throw ParseError(std::move(message) +
" in line " + std::to_string(m_line_no));
}
Expand Down Expand Up @@ -164,7 +164,7 @@ std::string ParseConfig::read_filter_string(It* it, const It end) {
}
else if (skip(it, end, "'") || skip(it, end, "\"")) {
// a string
const char mark[2] = { *(*it - 1), '\0' };
const char mark[2] = { *std::prev(*it), '\0' };
if (!skip_until(it, end, mark))
error("Unterminated string");
return std::string(begin + 1, *it - 1);
Expand Down Expand Up @@ -402,24 +402,33 @@ std::string ParseConfig::preprocess(It it, const It end) const {
// match read ident
result.append(preprocess_ident(std::string(begin, it)));
}
else {
else if (*it == '\'' || *it == '\"') {
// a string
const char mark[2] = { *it++, '\0' };
if (!skip_until(&it, end, mark))
error("Unterminated string");

// interpret escape sequence
if (*it == '\\' && std::next(it) != end) {
const auto c = [&]() {
switch (*std::next(it)) {
case 'n': return '\n';
case 't': return '\t';
case '\\': return '\\';
default: return '\0';
}
}();
if (c) {
result.push_back(c);
it += 2;
continue;
auto prev = char{ };
std::for_each(begin, it, [&](char c) {
if (prev == '\\') {
c = [&]() {
switch (c) {
case 'n': return '\n';
case 't': return '\t';
}
result.push_back('\\');
return c;
}();
prev = { };
}
}

else {
prev = c;
}
result.push_back(c);
});
}
else {
// output single character
result.append(begin, ++it);
}
Expand Down
2 changes: 1 addition & 1 deletion src/config/ParseConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ParseConfig {

using It = std::string::const_iterator;

[[noreturn]] void error(std::string message);
[[noreturn]] void error(std::string message) const;
void parse_line(It begin, It end);
void parse_context(It* begin, It end);
void parse_macro(std::string name, It begin, It end);
Expand Down
27 changes: 20 additions & 7 deletions src/test/test1_ParseConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,8 @@ TEST_CASE("Context macro", "[ParseConfig]") {
TEST_CASE("Macros", "[ParseConfig]") {
auto string = R"(
MyMacro = A{B}
MyMacro >> C
C >> MyMacro
MyMacro >> C # MyMacro
C >> MyMacro # MyMacro
)";
auto config = Config{ };
REQUIRE_NOTHROW(config = parse_config(string));
Expand All @@ -390,9 +390,9 @@ TEST_CASE("Macros", "[ParseConfig]") {
CHECK(format_sequence(config.contexts[0].outputs[1]) == "+A +B -B -A");

string = R"(
Macro1 = F
Macro2 = E Macro1 G
Macro3 =
Macro1 = F # >
Macro2 = E Macro1 G # Macro1
Macro3 = # -
Macro1 A Macro2 Macro3 >> Macro3 Macro2 B Macro1
)";
REQUIRE_NOTHROW(config = parse_config(string));
Expand All @@ -402,6 +402,19 @@ TEST_CASE("Macros", "[ParseConfig]") {
CHECK(format_sequence(config.contexts[0].inputs[0].input) == "+F ~F +A ~A +E ~E +F ~F +G ~G");
CHECK(format_sequence(config.contexts[0].outputs[0]) == "+E -E +F -F +G -G +B -B +F -F");

// do not substitute in string
string = R"(
ab = E F
X >> ab 'ab' ab
)";
REQUIRE_NOTHROW(config = parse_config(string));
REQUIRE(config.contexts[0].inputs.size() == 1);
REQUIRE(config.contexts[0].outputs.size() == 1);
REQUIRE(config.contexts[0].command_outputs.size() == 0);
CHECK(format_sequence(config.contexts[0].inputs[0].input) == "+X ~X");
CHECK(format_sequence(config.contexts[0].outputs[0]) ==
"+E -E +F -F !MetaLeft !MetaRight !ShiftLeft !ShiftRight !AltLeft !AltRight !ControlLeft !ControlRight +A -A +B -B +E -E +F -F");

// not allowed macro name
string = R"(
Space = Enter
Expand Down Expand Up @@ -512,13 +525,13 @@ TEST_CASE("Logical keys 2", "[ParseConfig]") {

TEST_CASE("String escape sequence", "[ParseConfig]") {
auto string = R"(
A >> 'n\n\tt'
A >> '\nnt\t'
)";

auto config = parse_config(string);
REQUIRE(config.contexts.size() == 1);
REQUIRE(config.contexts[0].outputs.size() == 1);
REQUIRE(format_sequence(config.contexts[0].outputs[0]) ==
"!MetaLeft !MetaRight !ShiftLeft !ShiftRight !AltLeft !AltRight !ControlLeft "
"!ControlRight +N -N +Enter -Enter +Tab -Tab +T -T");
"!ControlRight +Enter -Enter +N -N +T -T +Tab -Tab");
}

0 comments on commit 61c2661

Please sign in to comment.