Bug #16289 Documentation is incorrect about C prepared statement length parameter.
Submitted: 8 Jan 2006 20:55 Modified: 19 Apr 2006 17:22
Reporter: Eric Huss (Candidate Quality Contributor) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Documentation Severity:S3 (Non-critical)
Version:5.0.19-BK, 5.0/5.1 OS:Any (all)
Assigned to: Paul DuBois CPU Architecture:Any

[8 Jan 2006 20:55] Eric Huss
Description:
In the "C API Prepared Statement Data types" section of the documentation, it is not entirely correct with regards to the length parameter of a BIND structure.

It says: "A pointer to an unsigned long variable that indicates the actual number of bytes of data stored in *buffer."

This is not true.  It is *not* the actual number of bytes of data stored in *buffer in the case of when data is truncated.  In order to determine the actual number of bytes copied, you must do:  min(length, buffer_length)

How to repeat:
Select data with a prepared statement that causes truncation.  The length value will get set to the length of the untruncated data.

Suggested fix:
Set length to the *actual* number of bytes copied, or clarify the documentation that it is not the *actual* number of bytes in the case of truncation.
[24 Jan 2006 8:27] Valeriy Kravchuk
Thank you for a problem report. Can you, please, provide a small test case that proves that incorrectness in documentation?
[25 Jan 2006 2:39] Eric Huss
example that shows how length is set

Attachment: bind.c (application/octet-stream, text), 1.48 KiB.

[25 Jan 2006 2:39] Eric Huss
Patch to code to match documentation.

Attachment: length_patch (application/octet-stream, text), 405 bytes.

[25 Jan 2006 2:45] Eric Huss
I have added some attachments to this bug.  The first is an example of the behavior.  In a table, there is a row with a column with 50 bytes of data.  Using the prepared statement API, I attempt to SELECT it into a buffer that is 20 bytes.

It should print the following:
101
length=50 error=1

This means that mysql_stmt_fetch returned 101 (MYSQL_DATA_TRUNCATED) and that for that column, error was set to True (because it was truncated), but the length is stored as 50, instead of 20.

I can imagine that perhaps this was done on purpose, because theoretically it could be useful to know how big the buffer *should* be in order to store the value.  So, either the documentation or the code is wrong.

Also attached is a patch to libmysql.c that will change it to behave like the documentation says.  I sort of prefer this, because otherwise one would always need to do min(length, buffer_length) in order to determine the length of the data returned, and I can imagine someone forgetting to do that and blindly trying to read "length" bytes out of the buffer which would cause a buffer overflow.
[8 Feb 2006 12:13] Valeriy Kravchuk
Thank you for a bug report. Verified just as described with your test case on 5.0.19-BK (ChangeSet@1.2042, 2006-02-07 20:04:54+01:00):

openxs@suse:~/dbs/5.0> export CFG=/home/openxs/dbs/5.0/bin/mysql_config
openxs@suse:~/dbs/5.0> gcc -o 16289 `$CFG --cflags` 16289.c `$CFG --libs`
openxs@suse:~/dbs/5.0> export LD_LIBRARY_PATH=/home/openxs/dbs/5.0/lib/mysql/
openxs@suse:~/dbs/5.0> ./16289
101
length=50 error=1

So, this should be described in the documentation properly.
[9 Feb 2006 20:08] Konstantin Osipov
This is intentional. Also, in 5.0, a possible truncation state is returned by mysql_stmt_fetch (MYSQL_DATA_TRUNCATED): in case mysql_stmt_fetch returned 0, the value stored in *length is trustworthy and no min() is necessary.
The suggested procedure is therefore to always check for the return value of mysql_stmt_fetch.
[19 Apr 2006 17:22] Paul DuBois
Thank you for your bug report. This issue has been addressed in the
documentation. The updated documentation will appear on our website
shortly, and will be included in the next release of the relevant
product(s).