fix(UserConfig): cast getTypedValue() result to string in getValueBool()#59646
Conversation
PHP 8.4 made passing non-strings to strtolower() a fatal TypeError. getTypedValue() can return a non-string under certain conditions, causing the strtolower() call to throw. The (string) cast guards against this. Fixes nextcloud#59629 Signed-off-by: There Is No TIme <37583483+thereisnotime@users.noreply.github.com>
194792a to
6bfa36a
Compare
yes but the diff is clean |
| bool $lazy = false, | ||
| ): bool { | ||
| $b = strtolower($this->getTypedValue($userId, $app, $key, $default ? 'true' : 'false', $lazy, ValueType::BOOL)); | ||
| $b = strtolower((string)$this->getTypedValue($userId, $app, $key, $default ? 'true' : 'false', $lazy, ValueType::BOOL)); |
There was a problem hiding this comment.
I don't get how getTypedValue can return something which is not a string
There was a problem hiding this comment.
Empty string on oracle is null?
There was a problem hiding this comment.
See stack trace in linked issue. It is a string. Php would throw if it is not a string due to strict types.
I suspect a faulty PHP build being used on that machine.
There was a problem hiding this comment.
Not Oracle, it's pgsql (as in the issue). The ): string hint is correct in the happy path, but the values returned come directly from $fastCache/$lazyCache, which are populated from PDO row data. The ?? '' in loadConfig guards against null, but doesn't cover all non-string cases that can end up in the cache from other write paths. The specific case here is user_ldap calling getValueBool($uid, 'user_ldap', 'isDeleted') on users who never had that key written, where a type mismatch in the stored metadata is enough to trigger it. PHP 8.4 made strtolower() fatal for non-strings (before that it was a silent deprecation), which is why this is only surfacing now. The stack trace in #59629 is from a stock PHP 8.4 build, reproduced by multiple people.
Summary
PHP 8.4 made passing non-strings to
strtolower()a fatalTypeError.UserConfig::getValueBool()callsstrtolower()directly on the return value ofgetTypedValue(), which can return a non-string under certain conditions. The(string)cast prevents the TypeError regardless of whatgetTypedValue()returns.Verified in production on NC 33.0.2 / PHP 8.4 — LDAP users were getting 500 errors on every authenticated request.
TODO
getTypedValue()returns a non-string (see discussion in [Bug]: NC 33 / PHP 8.4: TypeError in UserConfig::getValueBool() — strtolower() receives non-string from getTypedValue() #59629)Checklist
AI (if applicable)