php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73002 bigendian64/php7/oci8: output bind-variables doesn't work
Submitted: 2016-09-02 11:14 UTC Modified: 2017-04-28 08:34 UTC
Votes:8
Avg. Score:4.8 ± 0.7
Reproduced:6 of 6 (100.0%)
Same Version:5 (83.3%)
Same OS:4 (66.7%)
From: lzsiga at freemail dot c3 dot hu Assigned:
Status: Open Package: OCI8 related
PHP Version: 7.* OS: 64-bit / BigEndian
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: lzsiga at freemail dot c3 dot hu
New email:
PHP Version: OS:

 

 [2016-09-02 11:14 UTC] lzsiga at freemail dot c3 dot hu
Description:
------------
Hi, I think I've found a little bug in component ext/oci8 that affects only 64-bit big-endian platforms.

In ext/oci8/oci8_statement.c:php_oci_bind_out_callback (line 1461) the program assumes that &val->string->len (type size_t *) can be type-casted to (ub4 *)

Well, that works on 32-bit platforms, also on 64-bit/little-endian platforms, but fails on bi-bit/big-endian platforms such as PowerPc64/Aix (size_t is eight bytes, ub4 is four bytes, and a simple type-cast does the wrong thing).

The attached patch seems to solve the problem.

Test script:
---------------
/* anonymous PL/SQL block */

BEGIN
  SELECT ename INTO :ename FROM emp WHERE empno=7876;
END;

Expected result:
----------------
ename=ADAMS

Actual result:
--------------
oci_execute(): ORA-03131: an invalid buffer was provided for the next piece

Patches

oci8_statement.patch_8_2_0 (last revision 2022-12-31 20:02 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_8_0_9 (last revision 2021-08-30 09:49 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_8_0_0 (last revision 2020-08-17 10:52 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_4_0boolean2 (last revision 2019-12-16 10:52 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_4_0boolean (last revision 2019-12-16 10:17 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_4_0 (last revision 2019-11-27 10:12 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_3_0_RC2 (last revision 2018-10-01 11:57 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_3_0 (last revision 2018-06-12 15:01 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_1_11 (last revision 2017-10-29 14:53 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_1_8 (last revision 2017-08-10 13:06 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_1_4 (last revision 2017-04-28 08:33 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_0_13_v2 (last revision 2016-11-14 19:12 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_0_13 (last revision 2016-11-14 12:11 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement_v2.patch_7_0_11 (last revision 2016-09-16 11:13 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch_7_0_11 (last revision 2016-09-16 10:28 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement_v2.patch (last revision 2016-09-08 10:22 UTC by lzsiga at freemail dot c3 dot hu)
oci8_statement.patch (last revision 2016-09-02 11:14 UTC by lzsiga at freemail dot c3 dot hu)

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-09-08 10:35 UTC] lzsiga at freemail dot c3 dot hu
Hi, I had to add some lines to prevent destruction of 'IN-only' bind variables. (I think 'php_oci_bind' should be reorganized, field 'dummy_len' replaced with fields 'maximum_len', 'before_exec_len' and 'after_exec_len'. Also it should be tracked in a boolean field if 'bind_out_callback' has been called on the field or not. If not, the bind-variable shouldn't be changed in 'bind_post_exec')
 [2016-09-16 10:29 UTC] lzsiga at freemail dot c3 dot hu
Modified the patch to match version 7.0.11
 [2017-04-28 08:34 UTC] lzsiga at freemail dot c3 dot hu
-PHP Version: 7.0.10 +PHP Version: 7.*
 [2017-04-28 08:34 UTC] lzsiga at freemail dot c3 dot hu
Moved the patch to versiom 7.1.4
 [2017-05-02 15:26 UTC] velazquez dot pascual at ciime dot mx
The same problem is observed in Solaris 11.3, in Sparc architecture. The proposed patch works. 

Thank you very much for posting the patch.
 [2017-08-10 09:12 UTC] lzsiga at freemail dot c3 dot hu
The changes in 7.1.8 rendered my patch unusable: the input-bind variables lose their content (guess their length become zero). Non-using my patch doesn't help, in that case oci_execute end is in ORA-3113 (disconnect). [Platform AIX, PowerPC/64-bit big-endian, Oracle client 12.1]
 [2017-08-10 13:08 UTC] lzsiga at freemail dot c3 dot hu
Ok, my fault; now I created a new patch with 'diff -c' for version 7.1.8
 [2017-08-11 05:12 UTC] sanjayrbhabhor at gmail dot com
We are  facing same issue with php-7.1.7, Apache -2.4.27 on power 7 AIX 7.1 64 bit. We had  added patch but it doesn't seem to work. Same "ORA-03131: an invalid buffer was provided for the next piece" error is giving.

Kindly help.
 [2017-08-11 08:08 UTC] sanjayrbhabhor at gmail dot com
Found solution for power bigendian 64 bit

*** ext / oci8 / oci8_statement.c Tue Aug 1 19:36:51 2017
 --- ../php-7.1.8-changed/ext/oci8/oci8_statement.c Thu Aug 10 13:25:20 2017
 ***************
 *** 979,995 ****
  		 }
  		 zval_dtor (val);
  		 ZVAL_NULL (val);
 !  } Else if (Z_TYPE_P (bind-> zval) == IS_STRING
 !  && Z_STRLEN_P (bind-> zval)> 0
 !  && Z_STRVAL_P (bind-> zval) [Z_STRLEN_P (bind-> zval)]! = '\ 0') {
 !  / * The post- PHP 5.3 feature for "interned" strings disallows
 !  * Their reallocation but (i) any IN binds either interned or
 !  * Should not already be null terminated and (ii) for OUT
 !  Binds, php_oci_bind_out_callback () should have allocated a
 !  * New string that we can modify here.
 !  * /
 !  Z_STR_P (bind-> zval) = zend_string_extend (Z_STR_P (bind-> zval), Z_STRLEN_P (bind-> zval) +1, 0);
 !  Z_STRVAL_P (bind-> zval) [Z_STRLEN_P (bind-> zval)] = '\ 0';
  	 } Else if (Z_TYPE_P (bind-> zval) == IS_ARRAY) {
  		 Int i;
  		 Zval * entry = NULL;
 --- 979,997 ----
  		 }
  		 zval_dtor (val);
  		 ZVAL_NULL (val);
 !  } Else if (Z_TYPE_P (bind-> zval) == IS_STRING) {
 !  Z_STRLEN_P (bind-> zval) = bind-> dummy_len;
 !  If (Z_STRLEN_P (bind-> zval)> 0 &&
 !  Z_STRVAL_P (bind-> zval) [Z_STRLEN_P (bind-> zval)]! = '\ 0') {
 !  / * The post- PHP 5.3 feature for "interned" strings disallows
 !  * Their reallocation but (i) any IN binds either interned or
 !  * Should not already be null terminated and (ii) for OUT
 !  Binds, php_oci_bind_out_callback () should have allocated a
 !  * New string that we can modify here.
 !  * /
 !  Z_STR_P (bind-> zval) = zend_string_extend (Z_STR_P (bind-> zval), Z_STRLEN_P (bind-> zval) +1, 0);
 !  Z_STRVAL_P (bind-> zval) [Z_STRLEN_P (bind-> zval)] = '\ 0';
 !  }
  	 } Else if (Z_TYPE_P (bind-> zval) == IS_ARRAY) {
  		 Int i;
  		 Zval * entry = NULL;
 ***************
 *** 1371,1376 ****
 --- 1373.1379 ----
  		 * Bufpp = 0;
  		 * Alenp = -1;
  		 * Indpp = (dvoid *) & phpbind-> indicator;
 + Phpbind-> dummy_len = 0;  / * So far, 'dummy_len' meant the maximum length;  From now, it is the actual length * /
  	 } Else if ((phpbind-> descriptor == 0) && (phpbind-> statement == 0)) {
  		 / * "Normal string bind * /
  		 convert_to_string (val);
 ***************
 *** 1386,1391 ****
 --- 1389.1395 ----
  		 If ((phpbind-> dummy_len> 0) && (phpbind-> dummy_len <* alenp))
  			 * Alenp = phpbind-> dummy_len;
  		 * Indpp = (dvoid *) & phpbind-> indicator;
 + Phpbind-> dummy_len = * alenp;  / * So far, 'dummy_len' meant the maximum length;  From now, it is the actual length * /
  	 } Else if (phpbind-> statement! = 0) {
  		 / * RSET * /
  		 * Bufpp = phpbind-> statement;
 ***************
 *** 1477,1484 ****
  		 ZVAL_STRINGL (val, NULL, Z_STRLEN (phpbind-> zval) + 1);
   #endif		
  
 !  / * XXX we assume that zend-zval len has 4 bytes * /
 !  * Alenpp = (ub4 *) & Z_STRLEN_P (phpbind-> zval);
  		 * Bufpp = Z_STRVAL_P (phpbind-> zval);
  		 * Piecep = OCI_ONE_PIECE;
  		 * Rcodepp = & phpbind-> retcode;
 --- 1481.1489 ----
  		 ZVAL_STRINGL (val, NULL, Z_STRLEN (phpbind-> zval) + 1);
   #endif		
  
 !  / * XXX we assume that zend-zval len has 4 bytes - does not work on big endian PowerPC-64 * /
 !  Phpbind-> dummy_len = Z_STRLEN_P (phpbind-> zval);
 !  * Alenpp = & phpbind-> dummy_len;
  		 * Bufpp = Z_STRVAL_P (phpbind-> zval);
  		 * Piecep = OCI_ONE_PIECE;
  		 * Rcodepp = & phpbind-> retcode;
 [2017-08-13 15:59 UTC] lzsiga at freemail dot c3 dot hu
The latest patch seems working on both php-7.1.7 and php-7.1.8
Here is a test-script: http://web.axelero.hu/lzsiga/oci_test.php -- I suggest using it with php-cli.
 [2017-10-29 15:09 UTC] lzsiga at freemail dot c3 dot hu
New patch added for 7.1.11; usage:

cd /usr/local/src/php-7.1.11; patch -p0 <oci8_statement.patch
 [2017-12-04 09:53 UTC] lzsiga at freemail dot c3 dot hu
Latest patch works with PHP-7.2.0 too.
Also I created a little graph to illustrate the problem (i.e. the difference between big-endian and little-endian, when it comes to mixing 32-bit and 64-bit)

0x1234 in eight byte

little endian
+----+----+----+----+----+----+----+----+
| 34 , 12 ; 00 , 00 | 00 , 00 ; 00 , 00 |
+----+----+----+----+----+----+----+----+
interpreted as int32: 0x00001234
<------------------>
interpreted as int64: 0x0000000000001234
<--------------------------------------->

big endian
+----+----+----+----+----+----+----+----+
| 00 , 00 ; 00 , 00 | 00 , 00 ; 12 , 34 |
+----+----+----+----+----+----+----+----+
interpreted as int32: 0x00000000
<------------------>
interpreted as int64: 0x0000000000001234
<--------------------------------------->

big endian
+----+----+----+----+----+----+----+----+
| 00 , 00 ; 12 , 34 | 00 , 00 ; 00 , 00 |
+----+----+----+----+----+----+----+----+
interpreted as int32: 0x00001234
<------------------>
interpreted as int64: 0x0000123400000000
<--------------------------------------->
 [2018-02-13 20:17 UTC] dave dot reddy at enbridge dot com
This patch appears to have fixed the issue for us as well.  AIX 7.1, 64bit, PHP 7.2.1, running fast-cgi daemons.
 [2018-08-29 20:21 UTC] dave dot reddy at enbridge dot com
Although this fixes the binding of numeric values, binding of boolean variable is still broken with this fix.
 [2018-08-30 09:05 UTC] lzsiga at freemail dot c3 dot hu
Hi Dave

Please provide an example regarding the problem of boolean values.
 [2019-06-03 16:53 UTC] davereddy at shaw dot ca
I missed your request for an example.

Please see the unit test embedded with the distribution (it fails):

ext/oci8/tests/bind_boolean_1.phpt
 [2019-11-27 10:12 UTC] lzsiga at freemail dot c3 dot hu
The following patch has been added/updated:

Patch Name: oci8_statement.patch_7_4_0
Revision:   1574849545
URL:        https://bugs.php.net/patch-display.php?bug=73002&patch=oci8_statement.patch_7_4_0&revision=1574849545
 [2019-11-27 10:41 UTC] lzsiga at freemail dot c3 dot hu
@davereddy
Hi, sorry for the delay; I tried `php bind_boolean_1.phpt` with 7.4.0; the very first test gave

    Test 1
    bool(false)
    bool(false)

while the file says it should be

    Test 1
    bool(true)
    bool(false)

I hope I'll be able look into this problem.
 [2019-12-13 18:04 UTC] lzsiga at freemail dot c3 dot hu
Ok, I've started to work on the booleans, see here: http://lzsiga.users.sourceforge.net/bigendian_64_oci8.txt
 [2019-12-16 10:17 UTC] lzsiga at freemail dot c3 dot hu
The following patch has been added/updated:

Patch Name: oci8_statement.patch_7_4_0boolean
Revision:   1576491454
URL:        https://bugs.php.net/patch-display.php?bug=73002&patch=oci8_statement.patch_7_4_0boolean&revision=1576491454
 [2019-12-16 10:26 UTC] lzsiga at freemail dot c3 dot hu
Please test the latest patch, it might solve the boolean-problem. The clue of the patch is this macro:

    #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
      #define LongPtr2Int32Ptr(longptr) ((int32_t *)(longptr))
    #else
      #define LongPtr2Int32Ptr(longptr) \
        ((int32_t *)((char *)(longptr)+(sizeof(long)-sizeof(int32_t))))
    #endif

It should work on both big-endian/32-bit and big-endian/64-bit; nonetheless it will fail 'long' isn't equal to 'zend_long' (e.g. Windows/64-bit)
 [2019-12-16 10:52 UTC] lzsiga at freemail dot c3 dot hu
The following patch has been added/updated:

Patch Name: oci8_statement.patch_7_4_0boolean2
Revision:   1576493564
URL:        https://bugs.php.net/patch-display.php?bug=73002&patch=oci8_statement.patch_7_4_0boolean2&revision=1576493564
 [2020-08-17 10:52 UTC] lzsiga at freemail dot c3 dot hu
The following patch has been added/updated:

Patch Name: oci8_statement.patch_8_0_0
Revision:   1597661527
URL:        https://bugs.php.net/patch-display.php?bug=73002&patch=oci8_statement.patch_8_0_0&revision=1597661527
 [2021-08-26 13:40 UTC] lzsiga at freemail dot c3 dot hu
Also there type 'oci_phpsized_int': its size on the Oracle version: 64-bit for Oracle 11+, 32-bit for older version.

Most likely it was meant to solve some problem, but of course there is no documentation about it.

When it is defined as 32-bit, it causes the same problem on big-endian platform.
 [2021-08-30 09:49 UTC] lzsiga at freemail dot c3 dot hu
The following patch has been added/updated:

Patch Name: oci8_statement.patch_8_0_9
Revision:   1630316990
URL:        https://bugs.php.net/patch-display.php?bug=73002&patch=oci8_statement.patch_8_0_9&revision=1630316990
 [2021-08-30 09:52 UTC] lzsiga at freemail dot c3 dot hu
Added another patch, which is simpler, but covers the phpsized_int's problem (64-bit big-endian, Oracle10) as well.
 [2021-08-30 11:45 UTC] lzsiga at freemail dot c3 dot hu
Created patch on github:
https://github.com/php/php-src/pull/7424
 [2021-10-26 11:19 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Oci8 problem on 64-bit bigendian platforms, bug#73002
On GitHub:  https://github.com/php/php-src/pull/7424
Patch:      https://github.com/php/php-src/pull/7424.patch
 [2022-12-31 20:02 UTC] lzsiga at freemail dot c3 dot hu
The following patch has been added/updated:

Patch Name: oci8_statement.patch_8_2_0
Revision:   1672516956
URL:        https://bugs.php.net/patch-display.php?bug=73002&patch=oci8_statement.patch_8_2_0&revision=1672516956
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Oct 07 20:01:27 2024 UTC