This project is archived and is in readonly mode.
mogrify silently truncates on null characters
-
Daniele Varrazzo
- State changed from new to invalid
I think it an expected behaviour: PostgreSQL internally uses mostly - or maybe uniquely - zero-terminated strings when dealing with text: only bytea can store zeros. It is forbidden to use zero into a string literal (see http://www.postgresql.org/docs/9.1/static/sql-syntax-lexical.html), and trying to produce one results in an error:
piro=> select chr(0); ERROR: null character not permittedPython strings don't have this limitation, so there is a mismatch between the two objects: not all Python strings can be represented as PostgreSQL text.
Because PQescapeString takes a C string as input, the first 0 is used as string delimiter: this is not surprising. There is no plan to work around using this function: it is the function we rely for the safety (against SQL injections) and if even it was able to encode a 0 in a string, something else downstream would most likely fail.
The NOTIFY payload is a string, so as such it would be wise to expect all the limitations of the PostgreSQL text. I see the notify payload is not decoded in python2: that was probably a bad choice (it is, in python3), but all psycopg2 on python2 is octet-oriented, so at least it is a consistent one. I'm afraid we'll have to live with this until some psycopg3.
I think inspecting all the strings passed by psycopg looking for zeros would have a noticeable performance effect: all the text arguments and derived are filtered through PQescapeString. Although raising a DataError would be a reasonable behaviour, I don't think dealing with \0 in strings is such a common case to deserve a dent in the general performance. It's true the argument is silently truncated, but that argument was created by a bug, otherwise you should have been using bytea data type and binary arguments in first place.