php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76322 Strings containing NULL-byte get truncated
Submitted: 2018-05-10 02:18 UTC Modified: 2021-08-09 08:41 UTC
Votes:2
Avg. Score:2.5 ± 0.5
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: morozov at tut dot by Assigned:
Status: Open Package: ibm_db2 (PECL)
PHP Version: 7.2.5 OS: Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2018-05-10 02:18 UTC] morozov at tut dot by
Description:
------------
If a value of a (VAR)?CHAR FOR BIT DATA field contains NULL-bytes, the value gets truncated after the first one.

Test script:
---------------
$stmt = db2_prepare($conn, 'CREATE TABLE TEST_TABLE(VAL VARCHAR(16) FOR BIT DATA NOT NULL)');
db2_execute($stmt);

$stmt = db2_prepare($conn, 'INSERT INTO TEST_TABLE VALUES(X\'410042\')');
db2_execute($stmt);

$stmt = db2_prepare($conn, 'SELECT VAL, LENGTH(VAL) LEN FROM test_table');
db2_execute($stmt);
$row = db2_fetch_assoc($stmt);

var_dump($row);

Expected result:
----------------
array(2) {
  'VAL' =>
  string(3) "A.B"
  'LEN' =>
  int(3)
}


Actual result:
--------------
array(2) {
  'VAL' =>
  string(1) "A"
  'LEN' =>
  int(3)
}


Patches

fix-76322 (last revision 2021-08-06 18:11 UTC by cmb@php.net)
fix_for_defect (last revision 2018-08-10 08:39 UTC by vnkbabu@php.net)

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-05-10 03:48 UTC] morozov at tut dot by
Combined with other issues, it can lead to a security hole like:

function register_user($email) {
    if (substr($email, -12) !== '@company.com') {
        die('Employees only');
    }

    $id = create_user($email);

    // later
    $email = get_user_email($id);
    send_activation($email);
}

register_user("evil@hacker.org\0@company.com");
 [2018-08-09 05:41 UTC] vnkbabu@php.net
Hi,
This is expected behavior, 
we are storing A"NULL" B in our database, while printing we are only printing A since after that we are encountering "NULL" hence not able to print B. From output we can check length retrieved from DB is 3.
Actual result:
--------------
array(2) {
  'VAL' =>
  string(1) "A"
  'LEN' =>
  int(3)

in HEX 00 corrosponds to "NULL" if you want to give "." then please use "2e".
 [2018-08-09 06:37 UTC] morozov at tut dot by
Could you please elaborate why this is expected behavior? The column definition contains "FOR BIT DATA" meaning it's just bytes, not printable characters. As far as the DB driver is concerned, strings in PHP are binary-safe, so it doesn't matter which bytes it contains. These bytes don't even have to be printed, they could be used as a binary representation of a structure (e.g. UUID) or a hash.

Other drivers (e.g. JDBC in IntelliJ IDEA) and other DB extensions in PHP (including mysqli, pdo_*, oci8 and sqlsrv) work with null-bytes correctly.

The dot in the output is to display the null byte, not the actual dot.
 [2018-08-09 09:19 UTC] vnkbabu@php.net
Hi,
What I meant was, when X'410042' is stored while printing PHP is truncating it as it encountered null, data is properly stored in application buffer after fetch.

var_dump() is not able to print beyond "NULL" but buffer holds complete data.
pasting below gdb output.
(gdb) p str
$15 = 0x7ffff6801118 "A"
(gdb) p/x *(str+1)
$16 = 0x0
(gdb) p/x *(str+2)
$17 = 0x42
and output also shows retrieved data is 3 length string.
array(2) {
  'VAL' =>
  string(1) "A"
  'LEN' =>
  int(3)  <<<<<<<<<<<<<<< 3 byte string.
}

Please let me know if I am misinterpreting something.

Thanks,
 [2018-08-09 16:49 UTC] morozov at tut dot by
Hi,

> What I meant was, when X'410042' is stored while printing PHP is truncating it as it encountered null, data is properly stored in application buffer after fetch.

Yes and no. A print/echo would truncate it but var_dump() wouldn't. The fact that var_dump() displays only one character means that the variable has one character. For example:
<?php

$a = "\x41\x00\x42"; // this is the same value as stored in the DB
var_dump($a);
// string(3) "A\000B" (this should be expected output in the original description, not sure if I can update it).

echo $a, PHP_EOL;
// A (even without the line feed)
?>

> var_dump() is not able to print beyond "NULL" but buffer holds complete data.

As you can see, it's not true.

> Please let me know if I am misinterpreting something.

Yes. The LEN() function is executed in the DB to show that the actual value stored in the DB is intact and is 3 bytes long. It doesn't mean that the PHP variable contains a 3-byte value.

The problem in the extension seems to be somewhere around:

https://github.com/php/pecl-database-ibm_db2/blob/a24fa9b37d658ea578b8483bddc8ad3d6f1b4262/ibm_db2.c#L6496

It uses the strlen() function to determine the string length but it stops on the first NULL-byte.
 [2018-08-10 08:36 UTC] vnkbabu@php.net
Thank you for clarification, as you mentioned in comment, use of strlen() was the issue. 

we need to replace strlen((char *)row_data->str_val) with out_length which holds the fetched output length.

will attach the path with the defect.

Thanks,
Abhinav
 [2018-08-10 08:39 UTC] vnkbabu@php.net
The following patch has been added/updated:

Patch Name: fix_for_defect
Revision:   1533890340
URL:        https://bugs.php.net/patch-display.php?bug=76322&patch=fix_for_defect&revision=1533890340
 [2018-08-10 16:59 UTC] morozov at tut dot by
Thank you, Abhinav! With the patch, the value is no longer truncated.
 [2019-04-06 16:14 UTC] morozov at tut dot by
Is there a chance the fix gets released? Looks like 2.0.7 still has this problem.
 [2021-08-06 18:11 UTC] cmb@php.net
The following patch has been added/updated:

Patch Name: fix-76322
Revision:   1628273509
URL:        https://bugs.php.net/patch-display.php?bug=76322&patch=fix-76322&revision=1628273509
 [2021-08-06 18:12 UTC] cmb@php.net
It seems to me that patch never has been merged.  I've attached a
patch which may solve the issue for current ibm_db2.  I cannot
test it, so you may want to give it a try.  If it's good, you may
consider to submit it as pull request[1]; it should probably
accompanied by a test.

[1] <https://github.com/php/pecl-database-ibm_db2/pulls>
 [2021-08-06 18:12 UTC] cmb@php.net
-Assigned To: +Assigned To: cmb
 [2021-08-08 04:45 UTC] morozov at tut dot by
Please see the PR with a test: https://github.com/php/pecl-database-ibm_db2/pull/14
 [2021-08-09 08:40 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Bug #76322: Strings containing NULL-byte get truncated
On GitHub:  https://github.com/php/pecl-database-ibm_db2/pull/14
Patch:      https://github.com/php/pecl-database-ibm_db2/pull/14.patch
 [2021-08-09 08:41 UTC] cmb@php.net
-Assigned To: cmb +Assigned To:
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Apr 27 13:01:30 2024 UTC