Add escaping and hardening

This commit is contained in:
Mike Bierlee 2022-09-29 02:04:58 +03:00
parent 01a555be55
commit bad8f0ec6d

View file

@ -431,10 +431,15 @@ class ConfigDictionary {
auto result = ""; auto result = "";
auto isParsingEnvVar = false; auto isParsingEnvVar = false;
auto isParsingDefault = false; auto isParsingDefault = false;
auto escapeNextCharacter = false;
auto varName = ""; auto varName = "";
auto defaultVarValue = ""; auto defaultVarValue = "";
void addVarValueToResult() { void addVarValueToResult() {
if (varName.length == 0) {
return;
}
string[] exceptionMessageParts; string[] exceptionMessageParts;
if (substituteEnvironmentVariables) { if (substituteEnvironmentVariables) {
@ -466,6 +471,17 @@ class ConfigDictionary {
} }
foreach (size_t i, char c; value) { foreach (size_t i, char c; value) {
if (escapeNextCharacter) {
result ~= c;
escapeNextCharacter = false;
continue;
}
if (c == '\\' && value.length.to!int - 1 > i && value[i + 1] == '$') {
escapeNextCharacter = true;
continue;
}
if (c == '$') { if (c == '$') {
isParsingEnvVar = true; isParsingEnvVar = true;
continue; continue;
@ -502,8 +518,12 @@ class ConfigDictionary {
result ~= c; result ~= c;
} }
if (varName.length > 0) { if (isParsingEnvVar) {
addVarValueToResult(); if (varName.length > 0) {
addVarValueToResult();
} else {
result ~= '$';
}
} }
return result; return result;
@ -939,5 +959,38 @@ version (unittest) {
assert(config.get("two") == "punch"); assert(config.get("two") == "punch");
} }
@("Escaping avoids variable substitution")
unittest {
auto config = new ConfigDictionary(new ObjectNode([
"only dollar": "\\$ESCAPE_WITH_MY_LIFE",
"with brackets": "\\${YOU WON'T GET ME}",
])
);
assert(config.get("only dollar") == "$ESCAPE_WITH_MY_LIFE");
assert(config.get("with brackets") == "${YOU WON'T GET ME}");
}
@("Wonky values")
unittest {
auto config = new ConfigDictionary(new ObjectNode([
"just a dollar": "$",
"final escape": "\\",
"escape with money": "\\$",
"brackets": "{}",
"empty bracket money": "${}",
"smackers": "$$$$$",
"weird bash escape thingy": "$$",
"escape room": "\\\\"
]));
assert(config.get("just a dollar") == "$");
assert(config.get("final escape") == "\\");
assert(config.get("escape with money") == "$");
assert(config.get("brackets") == "{}");
assert(config.get("empty bracket money") == "");
assert(config.get("smackers") == "$");
assert(config.get("escape room") == "\\\\");
}
//TODO: Test null nodes should gracefully fail //TODO: Test null nodes should gracefully fail
} }