Skip to content

Commit 0ceca90

Browse files
committed
security: replace unsafe /X+$/ idiom with rtrim
Problem: replace(/X+$/, '') is vulnerable to REDOS Solution: Replace all instances I could find with a custom rtrim
1 parent 4cc97f6 commit 0ceca90

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

lib/marked.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,32 @@
44
* https://github.com/markedjs/marked
55
*/
66

7+
// Return str with all trailing {c | all but c} removed
8+
// allButC: Default false
9+
function rtrim(str, c, allButC) {
10+
if (typeof(allButC) === 'undefined') {
11+
allButC = false;
12+
} else {
13+
allButC = true;
14+
}
15+
16+
if (str.length === 0) {
17+
return '';
18+
}
19+
20+
// ix+1 of leftmost that fits description
21+
// i.e. the length of the string we should return
22+
var curr = str.length;
23+
24+
while (0 < curr &&
25+
((allButC && str.charAt(curr - 1) !== c) ||
26+
(!allButC && str.charAt(curr - 1) === c))) {
27+
curr--;
28+
}
29+
30+
return str.substr(0, curr);
31+
}
32+
733
;(function(root) {
834
'use strict';
935

@@ -216,7 +242,7 @@ Lexer.prototype.token = function(src, top) {
216242
this.tokens.push({
217243
type: 'code',
218244
text: !this.options.pedantic
219-
? cap.replace(/\n+$/, '')
245+
? rtrim(cap, '\n')
220246
: cap
221247
});
222248
continue;
@@ -238,15 +264,11 @@ Lexer.prototype.token = function(src, top) {
238264
src = src.substring(cap[0].length);
239265
// cap[2] might be ' HEADING # '
240266
item = (cap[2] || '').trim();
241-
if (item.slice(-1) === '#') {
242-
// NB replace(/#+$/) is quadratic on mismatch because it's unanchored,
243-
// so we protect with if-check to ensure it won't mismatch.
244-
if (this.options.pedantic) {
245-
item = item.replace(/#+$/, '');
246-
} else {
247-
// CM requires a space before additional #s
248-
item = item.replace(/(\s|^)#+$/, '');
249-
}
267+
if (this.options.pedantic) {
268+
item = rtrim(item, '#');
269+
} else {
270+
// CM requires a space before additional #s
271+
item = item.replace(/(\s|^)#+$/, '');
250272
}
251273
item = item.trim();
252274
this.tokens.push({
@@ -1278,7 +1300,7 @@ function resolveUrl(base, href) {
12781300
if (/^[^:]+:\/*[^/]*$/.test(base)) {
12791301
baseUrls[' ' + base] = base + '/';
12801302
} else {
1281-
baseUrls[' ' + base] = base.replace(/[^/]*$/, '');
1303+
baseUrls[' ' + base] = rtrim(base, '/', true);
12821304
}
12831305
}
12841306
base = baseUrls[' ' + base];

0 commit comments

Comments
 (0)