diff options
author | Hisham Muhammad <hisham@gobolinux.org> | 2018-10-16 01:41:07 +0300 |
---|---|---|
committer | Thijs Schreijer <thijs@thijsschreijer.nl> | 2018-11-22 18:00:15 +0300 |
commit | 685fe6b1531df18bb9830985db2a46101c7fce62 (patch) | |
tree | 318fce45de30ac03e4eda240b44609396f0cc97c | |
parent | 52a1a249dc186403ffa673924cf526cfce68a90a (diff) |
Fix vulnerable pattern in pl.stringx.strip
Pattern backtracking can cause strip to become unbearably slow.
See http://stackstatus.net/post/147710624694/outage-postmortem-july-20-2016
The attached testcase in this commit demonstrates the problem.
Solution based on
https://github.com/leafo/lapis/commit/4a58f5c12582796b3c7e0ad784630fc6be56b92d
-rw-r--r-- | lua/pl/stringx.lua | 21 | ||||
-rw-r--r-- | tests/test-stringx.lua | 2 |
2 files changed, 18 insertions, 5 deletions
diff --git a/lua/pl/stringx.lua b/lua/pl/stringx.lua index 8bcc6a2..ce67095 100644 --- a/lua/pl/stringx.lua +++ b/lua/pl/stringx.lua @@ -16,6 +16,7 @@ local error = error local gsub = string.gsub local rep = string.rep local sub = string.sub +local reverse = string.reverse local concat = table.concat local append = table.insert local escape = utils.escape @@ -340,19 +341,29 @@ local function _strip(s,left,right,chrs) else chrs = '['..escape(chrs)..']' end + local f = 1 + local t if left then local i1,i2 = find(s,'^'..chrs..'*') if i2 >= i1 then - s = sub(s,i2+1) + f = i2+1 end end if right then - local i1,i2 = find(s,chrs..'*$') - if i2 >= i1 then - s = sub(s,1,i1-1) + if #s < 200 then + local i1,i2 = find(s,chrs..'*$',f) + if i2 >= i1 then + t = i1-1 + end + else + local rs = reverse(s) + local i1,i2 = find(rs, '^'..chrs..'*') + if i2 >= i1 then + t = -i2 + end end end - return s + return sub(s,f,t) end --- trim any whitespace on the left of s. diff --git a/tests/test-stringx.lua b/tests/test-stringx.lua index 8ee0f87..8052f28 100644 --- a/tests/test-stringx.lua +++ b/tests/test-stringx.lua @@ -229,6 +229,8 @@ asserteq(T(trim' a '), T'a') asserteq(T(trim' a '), T'a') asserteq(T(trim' ab cd '), T'ab cd') asserteq(T(trim' \t\r\n\f\va\000b \r\t\n\f\v'), T'a\000b') +local long = 'a' .. string.rep(' ', 200000) .. 'a' +asserteq(T(trim(long)), T(long)) -- more |