Fix problem with unsafe use of `String.prototype.replace()`

We were using `String.prototype.replace()` without addressing the
wrinkle that dollar signs in the replacement string have special
handling. This caused problems in situations where the replacement
string is derived from user input and contains dollar signs.

Fixes #2517
This commit is contained in:
Jermolene 2016-08-04 15:54:33 +01:00
parent 82694e1426
commit 08cfa88249
5 changed files with 16 additions and 7 deletions

View File

@ -19,6 +19,15 @@ exports.warning = function(text) {
console.log($tw.node ? "\x1b[1;33m" + text + "\x1b[0m" : text);
};
/*
Repeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string
*/
exports.replaceString = function(text,search,replace) {
return text.replace(search,function() {
return replace;
});
};
/*
Repeats a string
*/

View File

@ -75,9 +75,9 @@ FieldsWidget.prototype.execute = function() {
value = reMatch[1];
}
}
row = row.replace("$name$",fieldName);
row = row.replace("$value$",value);
row = row.replace("$encoded_value$",$tw.utils.htmlEncode(value));
row = $tw.utils.replaceString(row,"$name$",fieldName);
row = $tw.utils.replaceString(row,"$value$",value);
row = $tw.utils.replaceString(row,"$encoded_value$",$tw.utils.htmlEncode(value));
text.push(row);
}
}

View File

@ -82,8 +82,8 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
// Set an href
var wikiLinkTemplateMacro = this.getVariable("tv-wikilink-template"),
wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : "#$uri_encoded$",
wikiLinkText = wikiLinkTemplate.replace("$uri_encoded$",encodeURIComponent(this.to));
wikiLinkText = wikiLinkText.replace("$uri_doubleencoded$",encodeURIComponent(encodeURIComponent(this.to)));
wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",encodeURIComponent(this.to));
wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",encodeURIComponent(encodeURIComponent(this.to)));
wikiLinkText = this.getVariable("tv-get-export-link",{params: [{name: "to",value: this.to}],defaultValue: wikiLinkText});
if(tag === "a") {
domNode.setAttribute("href",wikiLinkText);

View File

@ -125,7 +125,7 @@ Widget.prototype.substituteVariableParameters = function(text,formalParams,actua
// If we've still not got a value, use the default, if any
paramValue = paramValue || paramInfo["default"] || "";
// Replace any instances of this parameter
text = text.replace(new RegExp("\\$" + $tw.utils.escapeRegExp(paramInfo.name) + "\\$","mg"),paramValue);
text = $tw.utils.replaceString(text,new RegExp("\\$" + $tw.utils.escapeRegExp(paramInfo.name) + "\\$","mg"),paramValue);
}
}
return text;

View File

@ -35,7 +35,7 @@ TiddlyWebAdaptor.prototype.getHost = function() {
];
for(var t=0; t<substitutions.length; t++) {
var s = substitutions[t];
text = text.replace(new RegExp("\\$" + s.name + "\\$","mg"),s.value);
text = $tw.utils.replaceString(text,new RegExp("\\$" + s.name + "\\$","mg"),s.value);
}
return text;
};