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

Commit 02b20ec

Browse files
committed
Merge branch '2.6' into 2.7
* 2.6: CS: fixes Translator component has default domain for null implemented no need to have default translation domain logic in 3 different places [Form] [TwigBridge] Bootstrap layout whitespace control [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 StringUtils::equals() arguments in RememberMe Cookie based implementation are confused CS: general fixes [SecurityBundle] removed a duplicated service definition and simplified others. Conflicts: src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
2 parents dcb1880 + 94465e0 commit 02b20ec

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
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
}

Http/RememberMe/TokenBasedRememberMeServices.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected function processAutoLoginCookie(array $cookieParts, Request $request)
5454
throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user)));
5555
}
5656

57-
if (true !== StringUtils::equals($hash, $this->generateCookieHash($class, $username, $expires, $user->getPassword()))) {
57+
if (true !== StringUtils::equals($this->generateCookieHash($class, $username, $expires, $user->getPassword()), $hash)) {
5858
throw new AuthenticationException('The cookie\'s hash is invalid.');
5959
}
6060

0 commit comments

Comments
 (0)