Bug #81382 [PATCH]: OUT-Variables result in ORA-03131
| From: | github.pkoch@dfgh.net | Date: | Sun, 29 Aug 2021 09:39:50 +0000 |
| Subject: | Bug #81382 [PATCH]: OUT-Variables result in ORA-03131 | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-236151@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=81382&edit=1
ID: 81382
Patch added by: github.pkoch@dfgh.net
Reported by: php-oci8 dot pkoch at dfgh dot net
Summary: OUT-Variables result in ORA-03131
Status: Duplicate
Type: Bug
Package: OCI8 related
Operating System: Solaris 11.4 SPARC 64 bigendian
PHP Version: 7.4.22
Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
The following pull request has been associated:
Patch Name: fix ora-03131 on bigendian 64bit machines
On GitHub: https://github.com/php/php-src/pull/7422
Patch: https://github.com/php/php-src/pull/7422.patch
Previous Comments:
------------------------------------------------------------------------
[2021-08-28 20:00:09] php-oci8 dot pkoch at dfgh dot net
Dear OCI8-developers:
ext/oci8/oci8_statement.c has some comments containing the string XXX. Seems as if the developer of
this sourcefile marked all lines that had to be fixed somehow.
One of these lines is line 1504:
/* XXX we assume that zend-zval len has 4 bytes */
*alenpp = (ub4*) &Z_STRLEN_P(val);
*bufpp = Z_STRVAL_P(val);
....
Of course this assumption is wrong on 64bit machines where Z_STRLEN is 8 bytes long (i.e. size_t)
and ub4 is 4 bytes long.
So when OCI8 retrieves a value it will store its length as as ub4-value into the first 4 bytes of a
size_t value. If the 64bit machine was little-endian the resulting size_t-value is equal to the
ub4-value. On big-endian machines the resulting size_t-value will be equal to the ub4-value shifted
to the left by 32bits. And this causes the ORA-03131 error.
If one wants to store a ub4-value into a size_t-value via a pointer then this pointer must point to
the first 4 bytes of the size_t value on little-endian systems and to the last 4 bytes of the size_t
value on big-endian systems. And one has to make sure, that the remaining 4 bytes will all be 0.
A better solution is to let the pointer point to a ub4-value and move the value to a size_t-value
later.
I added the following 4 lines after line 1505:
/* XXX we assume that zend-zval len has 4 bytes */
*alenpp = (ub4*) &Z_STRLEN_P(val);
if(sizeof(zend_long)==2*sizeof(ub4)){
zend_long z=1;
if(*(ub4*)&z==0) ++*alenpp;
}
*bufpp = Z_STRVAL_P(val);
....
Then everything works as expected.
Any comments?
Regards
Peter Koch
------------------------------------------------------------------------
[2021-08-25 14:44:23] cmb@php.net
> Bug https://bugs.php.net/bug.php?id=73002 from 2019 seems to
> deal with the same problem [â¦]
Then this is a duplicate of bug #73002.
> and provides patches.
Consider to provide pull requests[1] instead for better visibility.
[1] <https://github.com/php/php-src/pulls>
------------------------------------------------------------------------
[2021-08-25 14:38:09] php-oci8 dot pkoch at dfgh dot net
Description:
------------
Using Out-Variables results in
ORA-03131: an invalid buffer was provided for the next piece
when oci_execute() is called with PHP-7.4.22 under Solaris 11.4 64bit SPARC
Bug https://bugs.php.net/bug.php?id=73002 from
2019 seems to deal with the same problem and provides patches.
Test-Script runs fine with PHP-5.6.37 (both under Solaris 64bit and Linux 32/64bit). It also has no
problems with PHP-7.4.22 under Linux 64bit.
Test script:
---------------
$conn=oci_new_connect("scott","tiger","ORCL");
$stat=oci_parse($conn, "begin :out:='Hello World'; end;");
oci_bind_by_name($stat, ":out", $result, 100);
oci_execute($stat);
print "result=$result\n";
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=81382&edit=1