l() always calls check_plain() on the output of url() even though there's no XSS risk. This is due to #399488: Invalid markup generated by l(). (which mrbaileys pointed me to in irc) - check_plain() doesn't only fix XSS.

However, we only run into that issue if $options['query'] is passed - so should be able to skip the check_plain() check in other cases.

Patch is simple, here's micro benchmarks:

HEAD:
5.81 seconds for 100,000 iterations

Patch:
5.51 seconds for 100,000 iterations

That works out about a 3ms gain for every 1000 calls to l(). I've seen over 1500 calls to l() on some pages, so that's not too bad.

CommentFileSizeAuthor
#6 698992-encoding-madness.patch810 bytesDamien Tournoud
l.patch1.04 KBcatch
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

catch’s picture

Status: Active » Needs review
mfb’s picture

Status: Needs review » Closed (works as designed)

l() says it accepts external URLs, not just internal drupal paths, thus could contain & which needs escaping.

There's really no way to get around HTML-escaping pretty much anything that is being output as HTML -- unless you have some means of guaranteeing that escaping is irrelevant, such as an integer

HTML-escaping is not just about XSS risk, it's about proper HTML format.

catch’s picture

Status: Closed (works as designed) » Needs work

We could still add an $options key to l(), or strpos('&') or something, re-opening until this is exhausted, which it isn't just yet. Also crosslinking #687712: Optimize rdf.module for displaying multiple comments for background.

scor’s picture

subscribing

mfb’s picture

This kind of semi-HTML-escaping isn't developer friendly.
Imagine you are getting URLs from user input or external source like search engine API. If passed thru to l() as-is, the URL string would not be properly escaped. If the developer runs the string thru check_plain() before l() then it would be double-escaped by l().

Damien Tournoud’s picture

Status: Needs work » Needs review
FileSize
810 bytes

Nope. This call *is* required. We output something in HTML context, we need to encode it. drupal_attributes(), used on the same line, does exactly the same thing.

I'm tired of explaining that, so let's commit this small comment patch.

catch’s picture

Status: Needs review » Reviewed & tested by the community

Fine, fine.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed #6 to HEAD. Thanks.

Status: Fixed » Closed (fixed)
Issue tags: -Performance

Automatically closed -- issue fixed for 2 weeks with no activity.