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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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: Sat Dec 21 14:01:32 2024 UTC