php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79277 pdo_odbc accessing SAP 16.0 ASE Fatal error: Allowed memory size ...
Submitted: 2020-02-15 15:43 UTC Modified: 2020-03-22 12:31 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: khleung at isfactory dot com Assigned:
Status: Open Package: PDO ODBC
PHP Version: 7.4.2 OS: CentOS 7
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 this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: khleung at isfactory dot com
New email:
PHP Version: OS:

 

 [2020-02-15 15:43 UTC] khleung at isfactory dot com
Description:
------------
Having installed

php 7.4.2 on CentOS 7 1804 64-bit (3.10.0-1062.12.1.el7.x86_64) on a VMware host : 
2 GB ram, 250G HardDisk and 1 CPU Core. 
PHP and necessary modules are installed via yum install php and also by compiling using source from php-7.4.2.tar.gz

With SAP SDK for ASE binary file SDKASE160003P_7-21012007.TGZ installed

A testing script was prepared to check the connecting

It works fine to query a simple varchar(3) with 
"SELECT name FROM sysusers ORDER BY uid ASC"  
but it crashed : 
SELECT name, environ FROM sysusers ORDER BY uid ASC
or even 
SELECT top 1 name, environ FROM sysusers ORDER BY uid ASC


with following message:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4294967320 bytes) in /home/sybase/sybconnect1.php on line 16

sysusers table layout as follow
 Column_name Type     Length Prec Scale Nulls  
 ----------- -------- ------ ---- ----- -----  
 suid        int           4 NULL  NULL     0  
 uid         int           4 NULL  NULL     0  
 gid         int           4 NULL  NULL     0  
 name        char         30 NULL  NULL     0  
 environ     varchar     255 NULL  NULL     1  
 user_status smallint      2 NULL  NULL     0  


via UnixODBC Client tool : isql
/bin/isql SB007H sa [sapassword]

all of the above query works perfectly without any error


Test script:
---------------
[sybase@nagioshost lib]$ vi sybconnect.php
<?php

//PDO Driver Connect to Sybase
try {
    //$pdo = new PDO("odbc:Driver={Adaptive Server Enterprise};NA=lx007hsyb,5000;Uid=sa;Pwd=[sapassword];");
    $pdo = new PDO("odbc:SB007H", "sa", "[sapassword]");

    $pdo_status = "dsn: odbc:SB007H Connected to ASE 16\n";
    echo $pdo_status;

    $getUsers = $pdo->prepare('SELECT name FROM sysusers ORDER BY uid ASC');

    while ($row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) {
      $data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
      print $data;
    }
    $stmt = null;

	$getUsers->execute();
	$users = $getUsers->fetchAll();
	if ($users) {
	    foreach ($users as $user) {
	        echo  $user['name']."\n";
	    }
	} else {
	    trigger_error('No users.');
	}

} catch(PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}
:wq



Expected result:
----------------
sysusers contains only 20 rows and so it was expected
All query result set can shown   

Actual result:
--------------
pdo_odnc FetchAll queries with column of varchar(255) crashed
with following message:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4294967320 bytes) in /home/sybase/sybconnect1.php on line 16

Patches

init-displaysize (last revision 2020-02-23 12:04 UTC by cmb@php.net)
odbc_tracelog_revised (last revision 2020-02-16 06:19 UTC by khleung at isfactory dot com)
odbc_tracelog (last revision 2020-02-16 06:08 UTC by khleung at isfactory dot com)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-02-15 17:11 UTC] cmb@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: cmb
 [2020-02-15 17:11 UTC] cmb@php.net
Could you please provide an ODBC trace?  Make sure that it
contains no sensitive info before you post it.
 [2020-02-16 06:08 UTC] khleung at isfactory dot com
The following patch has been added/updated:

Patch Name: odbc_tracelog
Revision:   1581833287
URL:        https://bugs.php.net/patch-display.php?bug=79277&patch=odbc_tracelog&revision=1581833287
 [2020-02-16 06:19 UTC] khleung at isfactory dot com
The following patch has been added/updated:

Patch Name: odbc_tracelog_revised
Revision:   1581833940
URL:        https://bugs.php.net/patch-display.php?bug=79277&patch=odbc_tracelog_revised&revision=1581833940
 [2020-02-23 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2020-02-23 04:33 UTC] khleung at isfactory dot com
-Status: No Feedback +Status: Closed
 [2020-02-23 04:33 UTC] khleung at isfactory dot com
Problem still exits waiting for further recommendations
 [2020-02-23 07:01 UTC] requinix@php.net
-Status: Closed +Status: Re-Opened
 [2020-02-23 12:04 UTC] cmb@php.net
The following patch has been added/updated:

Patch Name: init-displaysize
Revision:   1582459492
URL:        https://bugs.php.net/patch-display.php?bug=79277&patch=init-displaysize&revision=1582459492
 [2020-02-23 12:05 UTC] cmb@php.net
Thanks for the ODBC trace, and sorry for the late reply!

It seems to me that we are not properly handling the retrieval of
the display size; the MS documentation of SQLColAttribute()[1]
states:

| Please note that some drivers may only write the lower 32-bit or
| 16-bit of a buffer and leave the higher-order bit unchanged.
| Therefore, applications should initialize the value to 0 before
| calling this function.

So can you please try the attached init-displaysize patch?

[1] <https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlcolattribute-function>
 [2020-02-23 12:05 UTC] cmb@php.net
-Status: Re-Opened +Status: Feedback
 [2020-03-08 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2020-03-08 07:48 UTC] khleung at isfactory dot com
[root@localhost ext]# cd /usr/local/src/php-7.4.2/ext/pdo_odbc/
[root@localhost pdo_odbc]# ls
config.m4   CREDITS        odbc_driver.lo  odbc_stmt.c   odbc_stmt.o  pdo_odbc.lo  php_pdo_odbc.h      tests
config.w32  odbc_driver.c  odbc_driver.o   odbc_stmt.lo  pdo_odbc.c   pdo_odbc.o   php_pdo_odbc_int.h
[root@localhost pdo_odbc]# vi odbc_stmt.c 

static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno)
{
        pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
        struct pdo_column_data *col = &stmt->columns[colno];
        RETCODE rc;
        SWORD   colnamelen;
        SQLULEN colsize;
        SQLLEN displaysize = 0;

...
:wq


[root@localhost pdo_odbc]# cd /usr/local/src/php-7.4.2/
[root@localhost php-7.4.2]# make
/bin/sh /usr/local/src/php-7.4.2/libtool --silent --preserve-dup-deps --mode=install cp ext/opcache/opcache.la /usr/local/src/php-7.4.2/modules
/bin/sh /usr/local/src/php-7.4.2/libtool --silent --preserve-dup-deps --mode=compile cc -I/usr/local/src/php-7.4.2/ext  -I/usr/include -DPDO_ODBC_TYPE=\"unixODBC\" -Iext/pdo_odbc/ -I/usr/local/src/php-7.4.2/ext/pdo_odbc/ -DPHP_ATOM_INC -I/usr/local/src/php-7.4.2/include -I/usr/local/src/php-7.4.2/main -I/usr/local/src/php-7.4.2 -I/usr/local/src/php-7.4.2/ext/date/lib -I/usr/include/libxml2 -I/usr/local/src/php-7.4.2/TSRM -I/usr/local/src/php-7.4.2/Zend    -I/usr/include -g -O2 -fvisibility=hidden -Wall -Wno-strict-aliasing -DZEND_SIGNALS   -c /usr/local/src/php-7.4.2/ext/pdo_odbc/odbc_stmt.c -o ext/pdo_odbc/odbc_stmt.lo 
/usr/local/src/php-7.4.2/ext/pdo_odbc/odbc_stmt.c: In function ‘odbc_stmt_describe’:
/usr/local/src/php-7.4.2/ext/pdo_odbc/odbc_stmt.c:573:4: warning: pointer targets in passing argument 3 of ‘SQLDescribeCol’ differ in signedness [-Wpointer-sign]
    &S->cols[colno].coltype, &colsize, NULL, NULL);
    ^
In file included from /usr/include/sqlext.h:43:0,
                 from /usr/include/sqlucode.h:784,
                 from /usr/local/src/php-7.4.2/ext/pdo_odbc/php_pdo_odbc_int.h:53,
                 from /usr/local/src/php-7.4.2/ext/pdo_odbc/odbc_stmt.c:29:
/usr/include/sql.h:644:24: note: expected ‘SQLCHAR *’ but argument is of type ‘char *’
     SQLRETURN  SQL_API SQLDescribeCol(SQLHSTMT StatementHandle,
                        ^
/usr/local/src/php-7.4.2/ext/pdo_odbc/odbc_stmt.c: In function ‘odbc_stmt_set_param’:
/usr/local/src/php-7.4.2/ext/pdo_odbc/odbc_stmt.c:781:4: warning: pointer targets in passing argument 2 of ‘SQLSetCursorName’ differ in signedness [-Wpointer-sign]
    rc = SQLSetCursorName(S->stmt, Z_STRVAL_P(val), Z_STRLEN_P(val));
    ^
In file included from /usr/include/sqlext.h:43:0,
....

Build complete.
Don't forget to run 'make test'.

[root@localhost php-7.4.2]# make install
Installing shared extensions:     /usr/lib/php/extensions/no-debug-non-zts-20190902/
Installing PHP CLI binary:        /usr/bin/
Installing PHP CLI man page:      /usr/php/man/man1/
Installing phpdbg binary:         /usr/bin/
Installing phpdbg man page:       /usr/php/man/man1/
Installing PHP CGI binary:        /usr/bin/
Installing PHP CGI man page:      /usr/php/man/man1/
Installing build environment:     /usr/lib/php/build/
Installing header files:          /usr/include/php/
Installing helper programs:       /usr/bin/
  program: phpize
  program: php-config
Installing man pages:             /usr/php/man/man1/
  page: phpize.1
  page: php-config.1
/usr/local/src/php-7.4.2/build/shtool install -c ext/phar/phar.phar /usr/bin
ln -s -f phar.phar /usr/bin/phar
Installing PDO headers:           /usr/include/php/ext/pdo/

[root@localhost php-7.4.2]# exit
[sybase@localhost ~]$ cd ~
[sybase@localhost ~]$ php sybconnect.php 
dsn: odbc:SB007H Connected to ASE 16

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4294967320 bytes) in /home/sybase/sybconnect.php on line 14
[sybase@localhost ~]$ which php
/usr/bin/php
[sybase@localhost ~]$ ls -l /usr/bin/php 
-rwxr-xr-x. 1 root root 32209632 Mar  8 23:34 /usr/bin/php
 [2020-03-08 09:11 UTC] requinix@php.net
-Status: No Feedback +Status: Re-Opened
 [2020-03-08 17:24 UTC] cmb@php.net
Thanks for checking!  Unfortunately, it's hard to guess what's
going on without being able to reproduce, and also because the
ODBC trace lacks some relevant information about out parameters
(although it looks generally fine).

I can imagine that the displaysize returned by SQLColAttribute()
is negative, but even in that case I cannot track down where that
excessive allocation would happen.  Still, it might help to try
with the following patch, which should print the retrieved
displaysizes to stderr:

 ext/pdo_odbc/odbc_stmt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c
index 18abc475b9..0d3cb45352 100644
--- a/ext/pdo_odbc/odbc_stmt.c
+++ b/ext/pdo_odbc/odbc_stmt.c
@@ -608,6 +608,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno)
 			return 0;
 		}
 	}
+	fprintf(stderr, "displaysize == %d\n", displaysize);
 	colsize = displaysize;
 
 	col->maxlen = S->cols[colno].datalen = colsize;
 [2020-03-08 17:25 UTC] cmb@php.net
-Status: Re-Opened +Status: Feedback
 [2020-03-22 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2020-03-22 12:23 UTC] hleung at isfactory dot com
[sybase@localhost ~]$ php sybconnect.php 
dsn: odbc:SB007H Connected to ASE 16
displaysize == 255
displaysize == 11
displaysize == 11
displaysize == 2
displaysize == 6
displaysize == 6
displaysize == 6
displaysize == 6
displaysize == 11
displaysize == 23
displaysize == 23
displaysize == 11
displaysize == 11
displaysize == 11
displaysize == 11
displaysize == 11
displaysize == 6
displaysize == 11
displaysize == 6
displaysize == 24
displaysize == 30
displaysize == 39
displaysize == 6
displaysize == 16
displaysize == 6
displaysize == 3
displaysize == 3
displaysize == 11
displaysize == 11

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4294967320 bytes) in /home/sybase/sybconnect.php on line 14
[sybase@localhost ~]$
 [2020-03-22 12:25 UTC] khleung at isfactory dot com
[sybase@localhost ~]$ php sybconnect.php 
dsn: odbc:SB007H Connected to ASE 16
displaysize == 255
displaysize == 11
displaysize == 11
displaysize == 2
displaysize == 6
displaysize == 6
displaysize == 6
displaysize == 6
displaysize == 11
displaysize == 23
displaysize == 23
displaysize == 11
displaysize == 11
displaysize == 11
displaysize == 11
displaysize == 11
displaysize == 6
displaysize == 11
displaysize == 6
displaysize == 24
displaysize == 30
displaysize == 39
displaysize == 6
displaysize == 16
displaysize == 6
displaysize == 3
displaysize == 3
displaysize == 11
displaysize == 11

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4294967320 bytes) in /home/sybase/sybconnect.php on line 14
[sybase@localhost ~]$


Seems not what you guess
 [2020-03-22 12:31 UTC] cmb@php.net
-Status: No Feedback +Status: Open -Assigned To: cmb +Assigned To:
 [2020-03-22 12:31 UTC] cmb@php.net
Indeed, apparently there are no negative display sizes.  I'm at a
loss; that probably needs to be debugged with a Sybase DB.
 [2020-07-01 19:52 UTC] net_surfer at mail dot com
It appears that the issue can be reproduced 100% of the time if a nullable varchar column getting selected actually contains a null value.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Thu Aug 06 14:01:25 2020 UTC