Throw ConversionException when unserialization fail for array and object types#3254
Throw ConversionException when unserialization fail for array and object types#3254morozov merged 1 commit intodoctrine:masterfrom seferov:array-type-convert
Conversation
morozov
left a comment
There was a problem hiding this comment.
@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.
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.
Please restore_error_handler().
| throw ConversionException::conversionFailedUnserialization($value, $this->getName(), $errstr); | ||
| }); | ||
|
|
||
| $val = unserialize($value); |
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
No need for $val variable, you should use return unserialize(...) directly here.
| { | ||
| error_reporting( (E_ALL | E_STRICT) - \E_NOTICE ); | ||
| $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.
You can avoid cryptic escaping by using double qoutes for the message.
| { | ||
| error_reporting( (E_ALL | E_STRICT) - \E_NOTICE ); | ||
| $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.
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
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.