TypeError: htmlspecialchars(): Argument #1 ($string) must be of type string leads to WSOD

Created on 1 August 2023, 11 months ago
Updated 23 August 2023, 10 months ago

Coming from a core issue ✨ Add Exception for TypeError Argument must be String in \Drupal\Component\Utility\Html escape{} Needs work which is not clear enough yet regarding core handling of such issues and by helping a user with a TypeError issue and to find its reasons, I made this finding. Many reports come up on D.O. lately because of the change to strict in PHP handling of Type. From the users report to me:

"After updating to latest module version and a successful user login, a WSOD appears with the following TypeError message on screen.

TypeError: htmlspecialchars(): Argument #1 ($string) must be of type string, array given in htmlspecialchars() (line 432 of core\lib\Drupal\Component\Utility\Html.php)

Making the admin path unmaintainable."

This is not the only issue like this, but I was sure each is caused by another reason. So I started to make some points and brought up some thoughts on this in Slack and had a very helpful chat with @smustgrave who suggested to print the array content in the moment the error gets initiated. So I did the following for the users case: Changing the respective code in the spot of the error message from

public static function escape($text): string {
  if (is_null($text)) {
    @trigger_error('Passing NULL to ' . __METHOD__ . ' is deprecated in drupal:9.5.0 and will trigger a PHP error from drupal:11.0.0. Pass a string instead. See https://www.drupal.org/node/3318826', E_USER_DEPRECATED);
  return '';
  }
  return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

to

public static function escape($text): string {
  if (is_array($text)) {
    var_dump($text);
  }
  if (is_null($text)) {
    @trigger_error('Passing NULL to ' . __METHOD__ . ' is deprecated in drupal:9.5.0 and will trigger a PHP error from drupal:11.0.0. Pass a string instead. See https://www.drupal.org/node/3318826', E_USER_DEPRECATED);
  return '';
  }
  return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

to print a var_dump from an array which actually should be string here. Which leads to the following output in place of the admin menu section.

/var/www/html/dp/web/core/lib/Drupal/Component/Utility/Html.php:431:
 
  'flag' => 
     
      '#theme' => string 'flags' 
      '#code' => string 'de' 
      '#source' => string 'language' 
  'title' => 
     
      '#markup' => string 'DE' 
/var/www/html/dp/web/core/lib/Drupal/Component/Utility/Html.php:431:
 
  'flag' => 
     
      '#theme' => string 'flags' 
      '#code' => string 'de' 
      '#source' => string 'language' 
  'title' => 
     
      '#markup' => string 'DE' 

Since the user runs an English/German multilanguage site with admin toolbar language switch enabled it was obvious which module is causing this. Disabling and uninstalling the module makes the error disappear.

Hope it helps others and maintainers to improve the code to fulfill PHP's new strict handling of var Types.

πŸ› Bug report
Status

Postponed: needs info

Version

2.0

Component

Code

Created by

πŸ‡©πŸ‡ͺGermany diqidoq Berlin | Hamburg | New York | London | Paris

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @diqidoq
  • πŸ‡©πŸ‡ͺGermany diqidoq Berlin | Hamburg | New York | London | Paris
  • πŸ‡©πŸ‡ͺGermany diqidoq Berlin | Hamburg | New York | London | Paris
  • πŸ‡©πŸ‡ͺGermany diqidoq Berlin | Hamburg | New York | London | Paris
  • πŸ‡©πŸ‡ͺGermany diqidoq Berlin | Hamburg | New York | London | Paris
  • πŸ‡©πŸ‡ͺGermany diqidoq Berlin | Hamburg | New York | London | Paris
  • πŸ‡«πŸ‡·France Chris64 France

    @diqidoq, could you provide an associated stack trace?

  • πŸ‡¬πŸ‡§United Kingdom james.williams

    This module currently sets the 'title' properties in the render array to a string / TranslatableMarkup, whereas the posted stack trace shows it has been set to an array (containing a #markup), alongside a 'flag' render array (using the 'flags' theme hook).

    But there are no mentions of 'flag' or 'flags' in the toolbar_language_switcher codebase (2.0.x-dev at least); are you running any other modules that could be adding these? Perhaps this module is currently incompatible with one you're using, because it assumes the language names would be strings rather than render arrays? (Which is why turning this module off would fix your problem of course.) If we can establish which module is conflicting, perhaps we can consider building support for language switcher links that are render arrays rather than simple strings. I suppose \Drupal\Core\Language\LanguageManagerInterface::getLanguageSwitchLinks() never actually promises what will be inside the array of links.

    Adjusting priority to normal, since this will only affect sites using the combination of conflicting modules, which is not possible with core and the most common contrib modules. (At least until we can be shown otherwise!)

  • πŸ‡«πŸ‡·France Chris64 France

    In #7 stack trace means the functions list. With a WSOD such a list may be in the log.

  • Status changed to Postponed: needs info 10 months ago
  • πŸ‡ΊπŸ‡¦Ukraine voleger Ukraine, Rivne

    Setting the appropriate status of the issue.

Production build 0.69.0 2024