ircmaxell/password_compat — pull request #40 by Jacques1 (2013-12-10 22:04:10+00:00)
Title: Incorrect handling of binary and ASCII strings

The library uses `strlen()` and `substr()` when dealing with binary or ASCII strings. This is incorrect. The functions might be overwritten by the mbstring library, in which case they operate on *characters* of the internal encoding rather than raw bytes.

This can lead to all kinds of problems:

- `password_get_info()` and `password_needs_rehash()` may break altogether due to `substr()` failing to extract the first 4 bytes of the hash
- `password_generate()` may reject perfectly valid salts, claiming they're too short
- The library may constantly read too many bytes from the PRNG
- `password_generate()` might also fail to truncate overly long salts and instead pass them on to `crypt()`

To verify the issue, load the mbstring library, set `mbstring.func_overload` to 2 and run the following code:

```php
mb_internal_encoding('utf-16');

// a perfectly valid salt consisting of 22 ASCII-encoded characters
$salt = str_repeat('e', 22);

// however, those are only 11 characters when the string is interpreted as UTF-16
echo strlen($salt), '
';

// the salt is rejected
echo password_hash('foo', PASSWORD_BCRYPT, array('salt' => $salt));
```