-
Notifications
You must be signed in to change notification settings - Fork 7.9k
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
@@ -4554,7 +4553,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
ZVAL_STRINGL(&new_val, "'f'", sizeof("'f'")-1); | |||
} | |||
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
@@ -4630,7 +4629,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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
@@ -4820,7 +4819,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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.
ext/pgsql/pgsql.c
Outdated
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
@@ -4782,7 +4781,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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
@@ -4630,7 +4629,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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
@@ -4554,7 +4553,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
ZVAL_STRINGL(&new_val, "'f'", sizeof("'f'")-1); | |||
} | |||
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
@@ -4679,7 +4678,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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
@@ -4740,7 +4739,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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
@@ -4586,7 +4585,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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
@@ -4679,7 +4678,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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
@@ -5037,7 +5040,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * | |||
} | |||
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.