summaryrefslogtreecommitdiffstats
path: root/Core
diff options
context:
space:
mode:
authorFabien Potencier <fabien.potencier@gmail.com>2015-03-27 11:19:51 +0100
committerFabien Potencier <fabien.potencier@gmail.com>2015-03-27 11:19:51 +0100
commit94465e02e58f9a17b29dd4afbcac5c02af4bf7e0 (patch)
treec1655995142c2ce7edcf8a47f1e3f39f2d1e51dd /Core
parentee7e5319d0a164be841bf1651c51fc2d09b17698 (diff)
parent6c8c751f7f5b09dbb608d4f43518dcb3fb214057 (diff)
downloadsymfony-security-94465e02e58f9a17b29dd4afbcac5c02af4bf7e0.zip
symfony-security-94465e02e58f9a17b29dd4afbcac5c02af4bf7e0.tar.gz
symfony-security-94465e02e58f9a17b29dd4afbcac5c02af4bf7e0.tar.bz2
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
Diffstat (limited to 'Core')
-rw-r--r--Core/Util/StringUtils.php49
1 files changed, 38 insertions, 11 deletions
diff --git a/Core/Util/StringUtils.php b/Core/Util/StringUtils.php
index e8f3e3b..e68347f 100644
--- a/Core/Util/StringUtils.php
+++ b/Core/Util/StringUtils.php
@@ -38,29 +38,56 @@ class StringUtils
*/
public static function equals($knownString, $userInput)
{
- $knownString = (string) $knownString;
- $userInput = (string) $userInput;
+ // Avoid making unnecessary duplications of secret data
+ if (!is_string($knownString)) {
+ $knownString = (string) $knownString;
+ }
+
+ if (!is_string($userInput)) {
+ $userInput = (string) $userInput;
+ }
if (function_exists('hash_equals')) {
return hash_equals($knownString, $userInput);
}
- $knownLen = strlen($knownString);
- $userLen = strlen($userInput);
+ $knownLen = self::safeStrlen($knownString);
+ $userLen = self::safeStrlen($userInput);
- // Extend the known string to avoid uninitialized string offsets
- $knownString .= $userInput;
+ if ($userLen !== $knownLen) {
+ return false;
+ }
- // Set the result to the difference between the lengths
- $result = $knownLen - $userLen;
+ $result = 0;
- // Note that we ALWAYS iterate over the user-supplied length
- // This is to mitigate leaking length information
- for ($i = 0; $i < $userLen; $i++) {
+ for ($i = 0; $i < $knownLen; $i++) {
$result |= (ord($knownString[$i]) ^ ord($userInput[$i]));
}
// They are only identical strings if $result is exactly 0...
return 0 === $result;
}
+
+ /**
+ * Returns the number of bytes in a string.
+ *
+ * @param string $string The string whose length we wish to obtain
+ *
+ * @return int
+ */
+ public static function safeStrlen($string)
+ {
+ // Premature optimization
+ // Since this cannot be changed at runtime, we can cache it
+ static $funcExists = null;
+ if (null === $funcExists) {
+ $funcExists = function_exists('mb_strlen');
+ }
+
+ if ($funcExists) {
+ return mb_strlen($string, '8bit');
+ }
+
+ return strlen($string);
+ }
}