Skip to content

Commit e053712

Browse files
committed
pdo_odbc: allocate sufficient space for retrieving unicode data
Closes GH-9498
1 parent 355baf9 commit e053712

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

ext/pdo_odbc/odbc_stmt.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,19 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno)
607607
}
608608
}
609609
colsize = displaysize;
610+
if ( S->cols[colno].coltype == SQL_WCHAR
611+
#ifdef SQL_WVARCHAR
612+
|| S->cols[colno].coltype == SQL_WVARCHAR
613+
#endif
614+
#ifdef SQL_WLONGVARCHAR
615+
|| S->cols[colno].coltype == SQL_WLONGVARCHAR
616+
#endif
617+
) {
618+
/* displaysize is counted by characters;
619+
for unicode, each could take up to 4 bytes in UTF-8;
620+
see https://www.rfc-editor.org/rfc/rfc3629 */
621+
colsize = displaysize * 4;
622+
}
610623

611624
col->maxlen = S->cols[colno].datalen = colsize;
612625
col->name = zend_string_init(S->cols[colno].colname, colnamelen, 0);

ext/pdo_odbc/tests/gh9498_1.phpt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
Bug GH-9498 (unicode string corruption during SELECT)
3+
--EXTENSIONS--
4+
pdo_odbc
5+
--SKIPIF--
6+
<?php
7+
require 'ext/pdo/tests/pdo_test.inc';
8+
PDOTest::skip();
9+
?>
10+
--FILE--
11+
<?php
12+
require 'ext/pdo/tests/pdo_test.inc';
13+
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
14+
$db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
15+
16+
$select_test = "SELECT
17+
CAST(0x72006f017e016f007600fd00 AS nvarchar(6)) AS pink_in_czech_binary_encoded_utf16le
18+
, CAST(0x6b26 AS nvarchar(1)) AS beamed_eighth_notes_binary_encoded_utf16le
19+
, NCHAR(0x266b) AS beamed_eighth_notes_nchar
20+
, N'♫' AS \"beamed_eighth_notes_u+266b_constant\"
21+
, N'růžový' AS pink_in_czech_unicode_string_constant
22+
, NCHAR(0xfb01) AS ligature_fi_nchar
23+
, N'𝄋' AS \"segno_u+1d10b_constant\"
24+
;";
25+
var_dump($db->query($select_test, \PDO::FETCH_ASSOC)->fetchAll());
26+
?>
27+
--EXPECT--
28+
array(1) {
29+
[0]=>
30+
array(7) {
31+
["pink_in_czech_binary_encoded_utf16le"]=>
32+
string(9) "růžový"
33+
["beamed_eighth_notes_binary_encoded_utf16le"]=>
34+
string(3) "♫"
35+
["beamed_eighth_notes_nchar"]=>
36+
string(3) "♫"
37+
["beamed_eighth_notes_u+266b_constant"]=>
38+
string(3) "♫"
39+
["pink_in_czech_unicode_string_constant"]=>
40+
string(9) "růžový"
41+
["ligature_fi_nchar"]=>
42+
string(3) "fi"
43+
["segno_u+1d10b_constant"]=>
44+
string(4) "𝄋"
45+
}
46+
}

0 commit comments

Comments
 (0)