]> granicus.if.org Git - php/commitdiff
Fixed bug #54379 (PDO_OCI: UTF-8 output gets truncated)
authorChristopher Jones <christopher.jones@oracle.com>
Thu, 2 Mar 2017 04:28:01 +0000 (15:28 +1100)
committerChristopher Jones <christopher.jones@oracle.com>
Thu, 2 Mar 2017 04:28:01 +0000 (15:28 +1100)
This was a modification of an incomplete PR #2276.

NEWS
ext/pdo_oci/oci_driver.c
ext/pdo_oci/oci_statement.c
ext/pdo_oci/php_pdo_oci_int.h
ext/pdo_oci/tests/bug54379.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index d156529ceca6960e12409460301af67e6a8e39a7..4d605efe6b67b55e5e49882a18b5ef0c3c720dfb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -60,6 +60,9 @@ PHP                                                                        NEWS
   . Fixed bug #74159 (Writing a large buffer to a non-blocking encrypted stream
     fails with "bad write retry"). (trowski)
 
+- PDO_OCI:
+  . Fixed bug #54379 (PDO_OCI: UTF-8 output gets truncated). (gureedo / Oracle)
+
 - Standard:
   . Fixed bug #74148 (ReflectionFunction incorrectly reports the number of
     arguments). (Laruence)
index 367f478e12482158fc698907c8c06a6a175debdc..a86b6d96130a6246835c6faf94f421a3b6ff055d 100644 (file)
@@ -699,6 +699,13 @@ static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ *
                goto cleanup;
        }
 
+       /* Get max character width */
+       H->last_err = OCINlsNumericInfoGet(H->env, H->err, &H->max_char_width, OCI_NLS_CHARSET_MAXBYTESZ);
+       if (H->last_err) {
+               oci_drv_error("OCINlsNumericInfoGet: OCI_NLS_CHARSET_MAXBYTESZ");
+               goto cleanup;
+       }
+
        dbh->methods = &oci_methods;
        dbh->alloc_own_columns = 1;
        dbh->native_case = PDO_CASE_UPPER;
index 5d3495788525660b65a808ade80954ee0f831807..306713bac3b96041968f0787c6255d61db2d9c61 100644 (file)
@@ -599,12 +599,12 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
                        } else if (dtype == SQLT_IBFLOAT || dtype == SQLT_IBDOUBLE) {
                                S->cols[colno].datalen = 1024;
 #endif
+                       } else if (dtype == SQLT_BIN) {
+                               S->cols[colno].datalen = (ub4) col->maxlen * 2; // raw characters to hex digits
                        } else {
-                               S->cols[colno].datalen = (ub4) col->maxlen;
-                       }
-                       if (dtype == SQLT_BIN) {
-                               S->cols[colno].datalen *= 3;
+                               S->cols[colno].datalen = (ub4) (col->maxlen * S->H->max_char_width);
                        }
+
                        S->cols[colno].data = emalloc(S->cols[colno].datalen + 1);
                        dtype = SQLT_CHR;
 
index ab437c14a8174d7301f5715783aed9e76ca208fb..5d066e53b8c1756244e21b3e940386ed30e89ff2 100644 (file)
@@ -38,6 +38,7 @@ typedef struct {
        ub4                     prefetch;
        ub2                     charset;
        sword           last_err;
+       sb4                     max_char_width;
 
        unsigned        attached:1;
        unsigned        _reserved:31;
diff --git a/ext/pdo_oci/tests/bug54379.phpt b/ext/pdo_oci/tests/bug54379.phpt
new file mode 100644 (file)
index 0000000..abb6bc7
--- /dev/null
@@ -0,0 +1,41 @@
+--TEST--
+Bug #54379 (PDO_OCI: UTF-8 output gets truncated)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_oci')) 
+die('skip not loaded');
+require dirname(__FILE__).'/../../pdo/tests/pdo_test.inc';
+if (!preg_match('/charset=.*utf8/i', getenv('PDOTEST_DSN')))
+die('skip not UTF8 DSN');
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require 'ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+try {
+        $db->exec("DROP TABLE test");
+} catch (Exception $e) {
+}
+$db->exec("CREATE TABLE test (col1 NVARCHAR2(20))");
+$db->exec("INSERT INTO test VALUES('12345678901234567890')");
+$db->exec("INSERT INTO test VALUES('あいうえおかきくけこさしすせそたちつてと')");
+$stmt = $db->prepare("SELECT * FROM test");
+$stmt->execute();
+var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
+$db->exec("DROP TABLE test");
+?>
+--EXPECTF--
+array(2) {
+  [0]=>
+  array(1) {
+    ["col1"]=>
+    string(20) "12345678901234567890"
+  }
+  [1]=>
+  array(1) {
+    ["col1"]=>
+    string(60) "あいうえおかきくけこさしすせそたちつてと"
+  }
+}