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:6
Avg. Score:4.7 ± 0.7
Reproduced:4 of 4 (100.0%)
Same Version:4 (100.0%)
Same OS:3 (75.0%)
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 Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or 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_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)

Add a Patch

Pull Requests

Add a Pull Request

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.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Fri May 24 07:01:26 2019 UTC