diff options
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Unwrap an avatar address in linear time
An author email of 16,000 "<" took three quarters of a second per log row, and one of 64,000 took twelve seconds.
-rw-r--r--custom/extensions/email-gravatar.lua9
-rw-r--r--custom/extensions/email-libravatar.lua9
-rw-r--r--tests/extensions/test-email-avatar.lua7
3 files changed, 19 insertions, 6 deletions
diff --git a/custom/extensions/email-gravatar.lua b/custom/extensions/email-gravatar.lua
index 836841f..eca31ee 100644
--- a/custom/extensions/email-gravatar.lua
+++ b/custom/extensions/email-gravatar.lua
@@ -81,9 +81,12 @@ local function normalize_email(email)
if email == nil then
return nil
end
- local inner = email:match("<(.*)>")
- if inner ~= nil then
- email = inner
+ -- The first "<" and the last ">" are found directly, because "<(.*)>"
+ -- backtracks to the end of the address from every "<" in it.
+ local open = email:find("<", 1, true)
+ local close = email:find(">[^>]*$")
+ if open and close and close > open then
+ email = email:sub(open + 1, close - 1)
end
email = trim(email):lower()
if email == "" then
diff --git a/custom/extensions/email-libravatar.lua b/custom/extensions/email-libravatar.lua
index 2b1fecd..3422dc1 100644
--- a/custom/extensions/email-libravatar.lua
+++ b/custom/extensions/email-libravatar.lua
@@ -79,9 +79,12 @@ local function normalize_email(email)
if email == nil then
return nil
end
- local inner = email:match("<(.*)>")
- if inner ~= nil then
- email = inner
+ -- The first "<" and the last ">" are found directly, because "<(.*)>"
+ -- backtracks to the end of the address from every "<" in it.
+ local open = email:find("<", 1, true)
+ local close = email:find(">[^>]*$")
+ if open and close and close > open then
+ email = email:sub(open + 1, close - 1)
end
email = trim(email):lower()
if email == "" then
diff --git a/tests/extensions/test-email-avatar.lua b/tests/extensions/test-email-avatar.lua
index bedcfe8..b4a4545 100644
--- a/tests/extensions/test-email-avatar.lua
+++ b/tests/extensions/test-email-avatar.lua
@@ -83,6 +83,13 @@ local started = os.clock()
render("<a" .. string.rep(" ", 40000) .. "b>", "x")
h.check("a long run of inner spaces is trimmed quickly", os.clock() - started < 0.5)
+started = os.clock()
+render(string.rep("<", 40000), "x")
+h.check("a long run of open brackets is unwrapped quickly", os.clock() - started < 0.5)
+
+h.check("the outermost brackets are the ones taken off",
+ hash_of(render("x <author@example.com> y", "x")) == plain)
+
if mode == "real" then
out = render("test@example.com", "x")
h.equals("a known address hashes to its published md5", hash_of(out), "55502f40dc8b7c769880b10874abc9d0")