-
Couldn't load subscription status.
- Fork 8k
ext/pgsql: php_pgsql_convert converts E_NOTICE to TypeError exceptions. #11238
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
Conversation
ext/pgsql/pgsql.c
Outdated
| php_error_docref(NULL, E_NOTICE, "Expects NULL or IPv4 or IPv6 address string for '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("Expects IPv4, IPv6 or null for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); |
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.
This feels more like a ValueError for the IPv4/6 addresses
ext/pgsql/tests/bug77047.phpt
Outdated
| var_dump(array_pop($row)); | ||
| var_dump(array_pop($row)); |
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.
We use space indents for PHP test files, (but tabs for C source files, confusing yes I know)
ext/pgsql/pgsql.c
Outdated
| php_error_docref(NULL, E_NOTICE, "Detected invalid value (%s) for PostgreSQL %s field (%s)", Z_STRVAL_P(val), Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_value_error("Detected invalid value (%s) for PostgreSQL '%s' field (%s)", Z_STRVAL_P(val), Z_STRVAL_P(type), ZSTR_VAL(field)); |
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.
This probably could be improved to say that the issue is to convert to a PostgreSQL bool?
Aside, the handling of IS_NULL seems slightly strange....
ext/pgsql/pgsql.c
Outdated
| php_error_docref(NULL, E_NOTICE, "Expects string, null, long or boolelan value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("Expects string, null long or boolean value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); |
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.
@kocsismate what is the standard phrasing for type errors again? And how do you think we could adjust it for these case?
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.
First of all, the currently executed function name should be at the beginning (e.g. pg_convert():). Then
probably the field type should be mentioned, like Field "%s" must be of type string|long|bool|null, %s given
| pg_insert($db, "bug77047", array("t" => NULL)); | ||
| pg_insert($db, "bug77047", array("t" => "")); | ||
| try { | ||
| pg_insert($db, "bug77047", array("t" => "13:31")); |
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.
I think you're only testing one case now, because when pg_insert (expectedly) fails, it will execute the catch and not execute the other pg_insert calls.
I guess it doesn't really matter here, but maybe you want the test to check if there are no errors thrown that shouldn't be thrown after the first failure. In which case you might not want to put a big try-catch around all calls.
1d78c4c to
7c9c2e4
Compare
|
ASAN Failure is expected but somehow it is still marked as FAIL... |
7c9c2e4 to
596ff5b
Compare
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.
Nits about using the standard type name boolean to bool and double to float, and needing to split one error case into 2 ideally.
ext/pgsql/pgsql.c
Outdated
| } | ||
| else { | ||
| php_error_docref(NULL, E_NOTICE, "Detected invalid value (%s) for PostgreSQL %s field (%s)", Z_STRVAL_P(val), Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_value_error("%s(): Field \"%s\" must be of type boolean, %s (%s) given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type), Z_STRVAL_P(val)); |
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.
| zend_value_error("%s(): Field \"%s\" must be of type boolean, %s (%s) given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type), Z_STRVAL_P(val)); | |
| zend_value_error("%s(): Field \"%s\" must be of type bool, %s (%s) given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type), Z_STRVAL_P(val)); |
We use bool instead of boolean for standard types
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for pgsql '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|double, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
We use float instead of double as the standard type
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|double, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); | |
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL or IPv4 or IPv6 address string for '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_value_error("Field \"%s\" must be of type IPv4|IPv6|null, given %s", ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
As this is a value error instead of a type error I think may need to be split into two different cases:
One that handles the types and the second one that checks that a string is a valid IP address.
596ff5b to
3e816a8
Compare
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.
Okay sorry for the previous crappy reviews.
I just had a proper look at what this code does, and it performs implicit type juggling to fit the PostgreSQL field types, as such we shouldn't be saying that we accept all those types when realistically we only want to support the target type.
One other thing that probably should be done is to point out when a float is passed for a field that expects an int but is not compatible (i.e. has a fractional part) by emitting a deprecation notice in line with PHP's standard behaviour.
Like I said in a comment, having a test that triggers all those conditions so that one can easily see what the error message being outputted is would be greatly helpful in making sense of what we should be doing.
| if (err == 2) { | ||
| zend_value_error("%s(): Field \"%s\" must be of type IPv4|IPv6|null, given %s", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(val)); | ||
| } else { | ||
| zend_type_error("%s(): Field \"%s\" must be of type IPv4|IPv6|null, given %s", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); | ||
| } |
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.
| if (err == 2) { | |
| zend_value_error("%s(): Field \"%s\" must be of type IPv4|IPv6|null, given %s", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(val)); | |
| } else { | |
| zend_type_error("%s(): Field \"%s\" must be of type IPv4|IPv6|null, given %s", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); | |
| } | |
| if (err == 2) { | |
| zend_value_error("%s(): Field \"%s\" must be a valid IPv4 or IPv6 address string, \"%s\" given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(val)); | |
| } else { | |
| zend_type_error("%s(): Field \"%s\" must be of type string|null, given %s", get_active_function_name(), ZSTR_VAL(field), zend_zval_value_name(val)); | |
| } |
As far as I can see the "type" zval should have nothing to do here. I think ideally it would be good to have a new test that tries to hit everyone of these type errors and value errors as it would be easier to see and correct the error messages.
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
Only just saw that "long" is used instead of the standard "int" PHP type.
Also it wants the time as an int so...
Moreover, there is the issue again about not actually providing the type of the actual passed value
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); | |
| zend_type_error("%s(): Field \"%s\" must be of type int|null, %s given", get_active_function_name(), ZSTR_VAL(field), zend_zval_value_name(val)); |
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for pgsql '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
Actually this field types just wants am int|null and does some type juggling to convert other types to int. however this maybe should follow the normal PHP semantics
ext/pgsql/pgsql.c
Outdated
| } | ||
| else { | ||
| php_error_docref(NULL, E_NOTICE, "Detected invalid value (%s) for PostgreSQL %s field (%s)", Z_STRVAL_P(val), Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_value_error("%s(): Field \"%s\" must be of type bool, %s (%s) given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type), Z_STRVAL_P(val)); |
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.
| zend_value_error("%s(): Field \"%s\" must be of type bool, %s (%s) given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type), Z_STRVAL_P(val)); | |
| zend_value_error("%s(): Field \"%s\" must be of type bool, invalid PostgreSQL string boolean value \"%s\" given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(val)); |
Erf I don't know what to do with this error message as what it wants is a valid PostgreSQL bool and we are parsing the string here...
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
Same here, it seems it only wants a float. But then this might require us to split the logic for NUMERIC and MONEY fields
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); | |
| zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
Similarly here, it does implicit type juggling to end up with a string.
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.
Final bits of review comments and then I think this is goot to land. Thank you!
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects string, null, long or boolelan value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|bool, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|bool, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); | |
| zend_type_error("%s(): Field \"%s\" must be of type string|null|int|bool, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type %s|null, %s given", get_active_function_name(), (data_type == PG_MONEY ? "money" : "float"), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
As int seems to be a reasonable, valid one too. Not sure if we should use money as a type but at this point it's better than what we have I think.
| zend_type_error("%s(): Field \"%s\" must be of type %s|null, %s given", get_active_function_name(), (data_type == PG_MONEY ? "money" : "float"), ZSTR_VAL(field), Z_STRVAL_P(type)); | |
| zend_type_error("%s(): Field \"%s\" must be of type %s|int|null, %s given", get_active_function_name(), (data_type == PG_MONEY ? "money" : "float"), ZSTR_VAL(field), Z_STRVAL_P(type)); |
ext/pgsql/pgsql.c
Outdated
| PGSQL_CONV_CHECK_IGNORE(); | ||
| if (err) { | ||
| php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); | ||
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
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.
| zend_type_error("%s(): Field \"%s\" must be of type string|null|long|float, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); | |
| zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); |
ext/pgsql/tests/bug71998.phpt
Outdated
| try { | ||
| @pg_insert($db, 'tmp_statistics', $data); | ||
| } catch (\ValueError $e) { | ||
| echo $e->getMessage() . PHP_EOL; |
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.
Nit: indent
392c1f0 to
6e04505
Compare
No description provided.