Bug #44278 [Com]: ODBC: nvarchar(max) mangled
| From: | chris at ocproducts dot com | Date: | Mon, 22 Jan 2018 17:56:48 +0000 |
| Subject: | Bug #44278 [Com]: ODBC: nvarchar(max) mangled | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-213663@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=44278&edit=1
ID: 44278
Comment by: chris at ocproducts dot com
Reported by: ethan dot nelson at ltd dot org
Summary: ODBC: nvarchar(max) mangled
Status: Re-Opened
Type: Bug
Package: PDO ODBC
PHP Version: 7
Block user comment: N
Private report: N
New Comment:
It'd take me a few days to get back into this and to the point of writing working PDO tests, I
just don't have that kind of time I'm afraid.
Previous Comments:
------------------------------------------------------------------------
[2018-01-22 16:31:18] ab@php.net
@chris at ocproducts dot com, thanks for the patch. Could you also add some tests, please? It
concerns both nvarchar and varchar now.
Thanks.
------------------------------------------------------------------------
[2017-11-18 11:34:09] cmb@php.net
> That other bug ticket is closed
To clarify: the ticket is private.
------------------------------------------------------------------------
[2017-11-18 11:30:06] chris at ocproducts dot com
On further testing, I found my patch was mostly correct, but insufficient. There is also another
manifestation of the bug fixed in #69975, but for varchar(max) rather than nvarchar(max).
I am uploading a new patch that covers this, improves code commenting a bit, fixes a couple of
mistakes in my prior patch, and is more defensive in case SQLBindCol never runs.
This resolves my confusion re "I also got a zero value", and I now understand the
asynchronous execution relates specifically to the behaviour of SQLBindCol binding rows as the
cursor advances (previously I thought it was something to do with app responsiveness in the face of
DB latency).
This is stable for me now. I got the full Composr CMS test set passing on ODBC using SQL Server
Express 2017, with webserver on a Mac using freeTDS. This was a long journey, quite a few issues,
notably also my bug filed as #75534.
------------------------------------------------------------------------
[2017-11-17 03:34:36] chris at ocproducts dot com
That other bug ticket is closed (I think I know why), and the issue still happens in PHP7.
The issue is caused because of a bad assumption in the code - that only binary or long results
require a full SQLGetData call (as opposed to SQLBindCol). In fact, if a vallen of <=0 is
returned by reference from SQLBindCol, a SQLGetData will be required because this may mean
SQL_NO_TOTAL (-4 value for vallen). This is actually a basic memory safety issue (vallen is used for
malloc), so this is worse than just data mangling.
Certainly FreeTDS is for me using a normal VARCHAR result (not LONGVARCHAR) for VARCHAR(MAX). Hence
breaking the aforementioned assumption.
I also got a zero value for vallen when running as an Apache module, which I had to treat with
SQLGetData too. This is confusing to me, I think it may have something to do with asynchronous
execution (this is how ODBC seems to be specified) but I can't find the PHP lib even touching
that, so I'm unsure.
I have been able to fix the issue on my machine and am about to attach a patch.
Truth is this code could do with a major refactoring. There is a lot of copy and pasting, and my
patch doesn't try and solve that.
------------------------------------------------------------------------
[2015-06-05 17:56:20] cmb@php.net
This is a duplicate of bug #54169 (well, actually it is the other
way round, but the other ticket already has a patch attached).
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=44278
--
Edit this bug report at https://bugs.php.net/bug.php?id=44278&edit=1