url_for accepts Symfony URLs with parameters like so:
module/action?key1=value1&key2=value2
Potentially remapping them according to routing rules and so on.
If the values passed need to contain the & sign, an escape mechanism is therefore needed. The standard mechanism for URLs like this everywhere else, of course, is urlencode().
However convertUrlStringToParameters unpacks the &-separated parameter list but never actually decodes the keys and values, accepting them as-is:
foreach ($matches as $match)
{
$params[$match[1][0]] = $match[2][0];
}
Subsequently both the "plain old query" fork and the "routed URL generator" fork urlencode the keys and values... which are already urlencoded... resulting in double-urlencoding and ensuing wailing and crying and gnashing of teeth.
The correct fix, as I understand it, is:
foreach ($matches as $match)
{
$params[urldecode($match[1][0])] = urldecode($match[2][0]);
}
This way the encoding is correctly undone before it is redone.