-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throw ConversionException when unserialization fail for array and object types #3254
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seferov does the error message contain the reason of the conversion failure or just states the fact? It looks like the latter.
I don't like the idea of error suppression since it leads to poor developer experience. Instead, we could try using a temporary error handler to capture the error and pass it to the exception message. Similarly to ConversionException::conversionFailedSerialization()
, we could create ConversionException::conversionFailedUnserialization()
.
throw ConversionException::conversionFailed($value, $this->getName()); | ||
} | ||
|
||
set_error_handler(function ($errno, $errstr) use ($value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use type hints for arguments and return types where possible.
}); | ||
|
||
$val = unserialize($value); | ||
set_error_handler(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please restore_error_handler()
.
throw ConversionException::conversionFailedUnserialization($value, $this->getName(), $errstr); | ||
}); | ||
|
||
$val = unserialize($value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of an exception, the error handler should be restored as well. Please use try/finally
.
$actualType = is_object($value) ? get_class($value) : gettype($value); | ||
|
||
return new self(sprintf( | ||
"Could not convert database value %s to %s, as an '%s' error was triggered by the unserialization", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use quotes around %s
for consistency with existing error messages.
if ($val === false && $value !== 'b:0;') { | ||
throw ConversionException::conversionFailed($value, $this->getName()); | ||
|
||
set_error_handler(function (int $errno, string $errstr) use ($value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last nitpick, please add : void
to the fn signature and squash all commits. The test looks fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also $code
instead of $errno
and $message
instead of $errstr
would be more readable. 😋
$actualType = is_object($value) ? get_class($value) : gettype($value); | ||
|
||
return new self(sprintf( | ||
"Could not convert database value '%s' to '%s', as an '%s' error was triggered by the unserialization", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since $value
will very likely be always string
(unlike the serialize case), I think it doesn't add any value to the error message.
I'd suggest something like this:
"Could not convert database value to '%s' as an error was triggered by the unserialization: '%s'"
if ($val === false && $value !== 'b:0;') { | ||
throw ConversionException::conversionFailed($value, $this->getName()); | ||
|
||
set_error_handler(function (int $errno, string $errstr) use ($value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also $code
instead of $errno
and $message
instead of $errstr
would be more readable. 😋
}); | ||
|
||
try { | ||
$val = unserialize($value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for $val
variable, you should use return unserialize(...)
directly here.
$this->expectException('Doctrine\DBAL\Types\ConversionException'); | ||
$this->expectExceptionMessage('Could not convert database value \'string\' to \'array\', as an \'unserialize(): Error at offset 0 of 7 bytes\' error was triggered by the unserialization'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can avoid cryptic escaping by using double qoutes for the message.
$this->expectException('Doctrine\DBAL\Types\ConversionException'); | ||
$this->expectExceptionMessage('Could not convert database value \'string\' to \'object\', as an \'unserialize(): Error at offset 0 of 7 bytes\' error was triggered by the unserialization'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can avoid cryptic escaping by using double qoutes for the message.
Please also squash changes into one commit. (Or we can do it before merge.) Thanks. 💯 |
…ect types cs fix object type conversionFailedUnserialization type hinting & finally restore error handler cs: use function type hint sort use alphabetically code quality improvements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @seferov!
Release v2.9.0 This is a minor release of Doctrine DBAL that aggregates over 40 fixes and improvements developed by 18 contributors over the last 5 months. This release includes all changes of the 2.8.x series, as well as feature additions and improvements that couldn't land in patch releases. ## Backwards Compatibility Breaks This doesn't contain any intentional Backwards Compatibility (BC) breaks. ## Deprecations * The usage of `NULL` to specify the absence of an offset in `LIMIT`ed queries is deprecated. Use `0` instead. * It's not recommended to rely on the default length specified by implementations of `Type`. These values are not used by the library and will be removed. * It's not recommended to rely on the string representation of `Type` objects. * Regular-expression based asset filters are deprecated in favor of callback-based as more extensible. * Calling `Statement::fetchColumn()` with an invalid column index is deprecated. * The `dbal:import` CLI command is deprecated. Please use other database client applications for import. Please see details in the [UPGRADE.md](UPGRADE.md) documentation. ## New Features * Added support for MariaDB 10.3. * Added support for Windows authentication for SQL Server. * Added support for column length in index definitions on MySQL. ## Improvements and Fixes * Implemented handling BLOB objects represented as streams in the MySQL (`mysqli`) driver. * Implemented handling BLOB objects represented as streams in the IDM DB2 driver. * DBAL is now continuously tested with the PDO driver for Oracle. * Implemented handling of URLs in master-slave and pooling-shard connection configuration. * The codebase is now fully compatible with the Doctrine Coding Standard v5.0. Total issues resolved: **45** **Deprecations:** - [3244: Deprecated dbal:import CLI command](doctrine#3244) thanks to @morozov - [3253: Deprecated usage of the NULL offset in LIMITed queries](doctrine#3253) thanks to @morozov - [3256: Deprecate Doctrine\DBAL\Types\Type::getDefaultLength()](doctrine#3256) thanks to @Majkl578 - [3258: Deprecate Doctrine\DBAL\Types\Type::&doctrine#95;&doctrine#95;toString()](doctrine#3258) thanks to @Majkl578 - [3316: Deprecated regex-based asset filters](doctrine#3316) thanks to @morozov - [3359: Removed DataAccessTest::testFetchColumnNonExistingIndex() since it covers a bug in PDO](doctrine#3359) thanks to @morozov **New Features:** - [2412: Add mysql specific indexes with lengths](doctrine#2412) thanks to @bburnichon - [3278: Add support for MariaDB 10.3](doctrine#3278) thanks to @javiereguiluz - [3283: MariaDB improvements, support 10.3](doctrine#3283) thanks to @sidz - [3333: Allow windows (userless/passwordless) authentication for SQL Server](doctrine#3333) thanks to @odinsey **Bug Fixes:** - [3355: Implemented comparison of default values as strings regardless of their PHP types](doctrine#3355) thanks to @morozov and @Majkl578 **Improvements:** - [3201: Fix support for URL to account for master-slave and pooling-shard connections](doctrine#3201) thanks to @stof - [3217: Fix that MysqliStatement cannot handle streams](doctrine#3217) thanks to @mpdude - [3235: Use PSR-4 autoloader](doctrine#3235) thanks to @Majkl578 - [3254: Throw ConversionException when unserialization fail for array and object types](doctrine#3254) thanks to @seferov - [3259: Update export ignores](doctrine#3259) thanks to @Majkl578 - [3309: Implemented handling BLOBs represented as stream resources for IBM DB2](doctrine#3309) thanks to @morozov and @mpdude - [3331: Fetch all should use the driver statement's fetchAll method](doctrine#3331) thanks to @michaelcullum **Documentation Improvements:** - [3223: GitHub template grammar/spelling fixes](doctrine#3223) thanks to @GawainLynch - [3232: Removed NOW() from QueryBuilder usage examples](doctrine#3232) thanks to @morozov - [3239: 2.8 in README & branch alias to 2.9](doctrine#3239) thanks to @Majkl578 - [3269: Fixed type hints in DockBlocks](doctrine#3269) thanks to @marforon - [3275: Add .doctrine-project.json to root of the project.](doctrine#3275) thanks to @jwage - [3276: Update homepage](doctrine#3276) thanks to @Majkl578 - [3280: Use behaviuor instead of behavior](doctrine#3280) thanks to @BackEndTea - [3285: Remove old comment from MysqliStatement](doctrine#3285) thanks to @mpdude - [3318: Removed link to www.doctrine-project.org from doc blocks](doctrine#3318) thanks to @morozov - [3319: remove ClassLoader](doctrine#3319) thanks to @garak - [3337: Fix of links in documentation](doctrine#3337) thanks to @SenseException - [3350: Remove pdo&doctrine#95;sqlsrv from known vendor issues list](doctrine#3350) thanks to @ostrolucky - [3357: Fix typo](doctrine#3357) thanks to @BenMorel - [3370: Removed 2.7 from README](doctrine#3370) thanks to @morozov **Code Quality Improvements:** - [3252: Replaced call&doctrine#95;user&doctrine#95;func&doctrine#95;array() of a fixed method with the usage of variadic arguments](doctrine#3252) thanks to @morozov - [3306: Fixed coding standard violations in the codebase](doctrine#3306) thanks to @morozov - [3303: Updated doctrine/coding-standard to 5.0, ](doctrine#3303) thanks to @morozov - [3317: Implemented proper escaping of string literals in platforms and schema managers](doctrine#3317) thanks to @morozov - [3363: Remove redundant implements](doctrine#3363) thanks to @BenMorel **Continuous Integration Improvements:** - [3307: Test against the latest stable sqlsrv extension](doctrine#3307) thanks to @morozov - [3320: Trying to fix failing DB builds](doctrine#3320) thanks to @morozov - [3325: Updated PHPUnit to 7.4](doctrine#3325) thanks to @morozov - [3339: ContinuousPHP configuration for PDO Oracle driver](doctrine#3339) thanks to @morozov - [3365: Reorganize Travis build matrix](doctrine#3365) thanks to @BenMorel # gpg: Signature made Tue Dec 4 05:44:06 2018 # gpg: using RSA key 374EADAF543AE995 # gpg: Can't check signature: public key not found # Conflicts: # README.md # lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php # lib/Doctrine/DBAL/Version.php
Summary
Problem: Converting invalid data with ArrayType/ObjectType throws PHP notice error.
Solution: inside convert method unserialize notice error can be suppressed since a proper exception (ConversionException) will be thrown right after that. No need to deal with error reporting.