Skip to content
This repository was archived by the owner on May 31, 2024. It is now read-only.

Commit 94465e0

Browse files
committed
Merge branch '2.3' into 2.6
* 2.3: CS: fixes Translator component has default domain for null implemented no need to have default translation domain logic in 3 different places [travis] Kill tests when a new commit has been pushed fixed CS Change behavior to mirror hash_equals() returning early if there is a length mismatch CS fixing Prevent modifying secrets as much as possible Update StringUtils.php Whitespace Update StringUtils.php CS: general fixes [SecurityBundle] removed a duplicated service definition and simplified others. Conflicts: src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget_collapsed.html.php src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml src/Symfony/Component/Console/Tests/Helper/LegacyTableHelperTest.php src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php
2 parents ee7e531 + 6c8c751 commit 94465e0

File tree

1 file changed

+38
-11
lines changed

1 file changed

+38
-11
lines changed

Core/Util/StringUtils.php

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,56 @@ private function __construct()
3838
*/
3939
public static function equals($knownString, $userInput)
4040
{
41-
$knownString = (string) $knownString;
42-
$userInput = (string) $userInput;
41+
// Avoid making unnecessary duplications of secret data
42+
if (!is_string($knownString)) {
43+
$knownString = (string) $knownString;
44+
}
45+
46+
if (!is_string($userInput)) {
47+
$userInput = (string) $userInput;
48+
}
4349

4450
if (function_exists('hash_equals')) {
4551
return hash_equals($knownString, $userInput);
4652
}
4753

48-
$knownLen = strlen($knownString);
49-
$userLen = strlen($userInput);
54+
$knownLen = self::safeStrlen($knownString);
55+
$userLen = self::safeStrlen($userInput);
5056

51-
// Extend the known string to avoid uninitialized string offsets
52-
$knownString .= $userInput;
57+
if ($userLen !== $knownLen) {
58+
return false;
59+
}
5360

54-
// Set the result to the difference between the lengths
55-
$result = $knownLen - $userLen;
61+
$result = 0;
5662

57-
// Note that we ALWAYS iterate over the user-supplied length
58-
// This is to mitigate leaking length information
59-
for ($i = 0; $i < $userLen; $i++) {
63+
for ($i = 0; $i < $knownLen; $i++) {
6064
$result |= (ord($knownString[$i]) ^ ord($userInput[$i]));
6165
}
6266

6367
// They are only identical strings if $result is exactly 0...
6468
return 0 === $result;
6569
}
70+
71+
/**
72+
* Returns the number of bytes in a string.
73+
*
74+
* @param string $string The string whose length we wish to obtain
75+
*
76+
* @return int
77+
*/
78+
public static function safeStrlen($string)
79+
{
80+
// Premature optimization
81+
// Since this cannot be changed at runtime, we can cache it
82+
static $funcExists = null;
83+
if (null === $funcExists) {
84+
$funcExists = function_exists('mb_strlen');
85+
}
86+
87+
if ($funcExists) {
88+
return mb_strlen($string, '8bit');
89+
}
90+
91+
return strlen($string);
92+
}
6693
}

0 commit comments

Comments
 (0)