It's possible to pollute the path mapping cache via calls to drupal_lookup_path().
Calling drupal_lookup_path('source', $alias) with a wrongly-cased $alias will result in the path cache containing the wrongly-cased alias. However, the very first time drupal_lookup_path('alias', $path) is called the path mapping cache gets completely destroyed and rebuilt; this time with the correctly-cased aliases, so the bad cache doesn't really hurt us as long as the calls are made in that order. However, if drupal_lookup_path('source', $alias) is called with a wrongly-cased $alias *after* drupal_lookup_path('alias', $path) is called then it will fail to find any matching entry in the cache (due to the case-sensitive array_search comparison) and it will end up polluting the cache with the wrongly-cased entry which will never get fixed.
Specifically, I saw this as a result of the interaction of some contrib modules. Global Redirect couldn't retrieve the correctly-cased version of the alias without clearing the path cache. See a few related issues where this problem has arisen:
#2048137: Canonical redirect breaks path cache
#2400521: Breaks path cache
#1983954: Case Sensitive URL Checking does not works when enable both boost and redirect
To reproduce:
- Shield and Global Redirect modules installed
- Configured Global Redirect to redirect all requests to the correctly-cased version of an alias
- Have an alias content/test
- Attempt to access content/tESt
- Page loads at content/tESt without redirecting me to the correct path (content/test)
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | interdiff.txt | 560 bytes | azinck |
| #3 | drupal-path_cache_pollution-2400539-3.patch | 2.29 KB | azinck |
| #1 | drupal-path_cache_pollution-2400539-1.patch | 1.76 KB | azinck |
Comments
Comment #1
azinck commentedComment #2
azinck commentedHave looked into this a bit more. Here's the problem in a nutshell:
Calling drupal_lookup_path('source', $alias) with a wrongly-cased $alias will result in the path cache containing the wrongly-cased alias. However, the very first time drupal_lookup_path('alias', $path) is called the path mapping cache gets completely destroyed and rebuilt; this time with the correctly-cased aliases, so the bad cache doesn't really hurt us as long as the calls are made in that order. However, if drupal_lookup_path('source', $alias) is called with a wrongly-cased $alias *after* drupal_lookup_path('alias', $path) is called then it will fail to find any matching entry in the cache (due to the case-sensitive array_search comparison) and it will end up polluting the cache with the wrongly-cased entry which will never get fixed.
As far as I can tell these findings further confirm the validity of the patch in #1.
Comment #3
azinck commentedSmall tweak that's tangentially related to the initial issue. IMO calling drupal_get_path_alias('nOde/123') should return the same thing as drupal_get_path_alias('node/123'). We're otherwise treating the paths the same so I don't see any rationale for handling the alias lookup differently.
Comment #4
azinck commentedComment #5
azinck commentedComment #6
heddnCan we confirm this isn't an issue in D8? With the re-done routing, this is almost certainly not an issue, but it never hurts to confirm.
Comment #7
jamesdevware commentedComment #8
eugene bocharov commentedEncountered the same problem with boost module enabled. After some debugging came to the same approache as #1. The patch works fine, thanks.
Not sure about the addition in #3
I think system paths not necessarily should be lowercase, maybe a custom module could provide menu item with upper letters in it.
But #1 patch is fine by me.