php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39756 [PATCH] Crashes in fetching resultsets with LONG ASCII columns from MaxDB
Submitted: 2006-12-06 15:16 UTC Modified: 2010-06-21 00:27 UTC
Votes:9
Avg. Score:5.0 ± 0.0
Reproduced:9 of 9 (100.0%)
Same Version:4 (44.4%)
Same OS:5 (55.6%)
From: tobias dot barth at web-arts dot com Assigned: felipe (profile)
Status: Closed Package: ODBC related
PHP Version: 5.2 OS: SuSE Linux 10.1
Private report: No CVE-ID: None
 [2006-12-06 15:16 UTC] tobias dot barth at web-arts dot com
Description:
------------
I got SuSE 10.1, a self-compiled php 4.4.4 (also tried the php5-5.1.2-29.22 from SuSE and php 5.1.4 from the php website with the same result), unixODBC, apache 2.2 and MaxDB 7.6 on an AMD X2 x86_64 platform with the following table:

CREATE TABLE "PRESSESTIMMEN"
(
	"ID"               Fixed (18,0)    NOT NULL,
	"TITLE"               Varchar (100) ASCII,
	"HEADLINE"               Varchar (250) ASCII,
	"DATUM"               Date,
	"TEXT"               Long ASCII,
	"BILD_NAME"               Varchar (100) ASCII,
	"BILD_TYPE"               Varchar (120) ASCII,
	"BILD_SIZE"               Fixed (18,0),
	"BILD"               Char (2) ASCII,
	"ARCHIVDATUM"               Date,
	PRIMARY KEY ("ID")
)

doing a 

$a = odbc_exec ($dbcon, select id,title,headline,datum from pressestimmen");
while (odbc_fetch_into ($a, $row)) {
...
}

works well. But if I modify the select statement:

$a = odbc_exec ($dbcon, select * from pressestimmen");

only reads out the first line. The second call to "odbc_fetch_into" crashes. in the error_log of apache, I see 
*** glibc detected *** /usr/sbin/httpd2-prefork: free(): invalid pointer: 0x0000
555555c2df40 ***

If I modify the select statement to
    $a = odbc_exec ($dbcon, "select id,title,headline,datum,text from pressestimmen");

I get the same problems. I think it is because of the data type "long ascii" of the "text" column. I had this software running on php3 and php4 since the days of SuSE 7.0 on 32 bit platforms until SuSE 10.0 and SuSE 10.1 on a dual XEON 32 bit platform without problems, but now on the 64 bit machine, it crashes. So I think, it is an 64 Bit problem with the Long Ascii data type.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-12-06 17:04 UTC] tony2001@php.net
Please try this patch:
http://tony2001.phpclub.net/dev/tmp/bug39756.diff
 [2006-12-06 18:34 UTC] tobias dot barth at web-arts dot com
okay, I will create a test script. in the meantime - perhaps this trace could help?

---Type <return> to continue, or q <return> to quit---
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 47707950089888 (LWP 29782)]
_efree (ptr=0x640000003c) at /usr/src/php4-STABLE-200612061330/Zend/zend_alloc.c:256
256             CALCULATE_REAL_SIZE_AND_CACHE_INDEX(p->size);
(gdb) bt
#0  _efree (ptr=0x640000003c) at /usr/src/php4-STABLE-200612061330/Zend/zend_alloc.c:256
#1  0x00002b63e17b0463 in _free_odbc_result (rsrc=<value optimized out>) at /usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c:173
#2  0x00002b63e1869efe in list_entry_destructor (ptr=<value optimized out>) at /usr/src/php4-STABLE-200612061330/Zend/zend_list.c:177
#3  0x00002b63e186983a in zend_hash_del_key_or_index (ht=0x2b63e19faaa8, arKey=0x0, nKeyLength=0, h=12, flag=<value optimized out>)
    at /usr/src/php4-STABLE-200612061330/Zend/zend_hash.c:529
#4  0x00002b63e186a107 in _zend_list_delete (id=<value optimized out>) at /usr/src/php4-STABLE-200612061330/Zend/zend_list.c:56
#5  0x00002b63e1870c08 in zend_assign_to_variable (result=0x555555c63288, op1=<value optimized out>, op2=0x555555c632c8, value=0x555555bfea08,
    type=0, Ts=0x7fffccb7aa00) at /usr/src/php4-STABLE-200612061330/Zend/zend_execute.c:483
#6  0x00002b63e187677c in execute (op_array=0x555555c04f38) at /usr/src/php4-STABLE-200612061330/Zend/zend_execute.c:1393
#7  0x00002b63e18782a9 in execute (op_array=0x555555b651c0) at /usr/src/php4-STABLE-200612061330/Zend/zend_execute.c:2278
#8  0x00002b63e1876249 in execute (op_array=0x555555b256c8) at /usr/src/php4-STABLE-200612061330/Zend/zend_execute.c:1725
#9  0x00002b63e18782a9 in execute (op_array=0x555555b20ef8) at /usr/src/php4-STABLE-200612061330/Zend/zend_execute.c:2278
#10 0x00002b63e1862a9a in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/php4-STABLE-200612061330/Zend/zend.c:935
#11 0x00002b63e18344b7 in php_execute_script (primary_file=0x7fffccb995d0) at /usr/src/php4-STABLE-200612061330/main/main.c:1752
#12 0x00002b63e188083d in php_handler (r=0x555555b0d0a8) at /usr/src/php4-STABLE-200612061330/sapi/apache2handler/sapi_apache2.c:581
#13 0x000055555558c6ba in ap_run_handler () from /usr/sbin/httpd2-prefork
#14 0x000055555558faa2 in ap_invoke_handler () from /usr/sbin/httpd2-prefork
#15 0x000055555559a1c8 in ap_process_request () from /usr/sbin/httpd2-prefork
#16 0x0000555555597409 in ap_register_input_filter () from /usr/sbin/httpd2-prefork
#17 0x0000555555593772 in ap_run_process_connection () from /usr/sbin/httpd2-prefork
#18 0x000055555559dc09 in ap_graceful_stop_signalled () from /usr/sbin/httpd2-prefork
#19 0x000055555559de0e in ap_graceful_stop_signalled () from /usr/sbin/httpd2-prefork
#20 0x000055555559e911 in ap_mpm_run () from /usr/sbin/httpd2-prefork
#21 0x0000555555579cb8 in main () from /usr/sbin/httpd2-prefork
(gdb) quit
 [2006-12-06 18:47 UTC] tony2001@php.net
Oh, so which one of these two segfaults do you actualy encounter?
One of them doesn't look to be ODBC related and another one seem to be caused by your database, which for some reason returns lengths == 62 and value == NULL (which is most likely a bug in the MaxDB ODBC driver).
 [2006-12-07 01:10 UTC] tobias dot barth at web-arts dot com
I have now created an example, which always crashes on my machine.

1) create the user "CRASHTEST" on a MaxDB 7.6 database (log in as DBA in the sqlstudio and type: create user CRASHTEST password CRASHTEST resource not exclusive)

2) login in as user "CRASHTEST" and run the following sql script:

CREATE TABLE "PRESSESTIMMEN"
(
	"ID"               Fixed (18,0)    NOT NULL,
	"TITLE"               Varchar (100) ASCII,
	"HEADLINE"               Varchar (250) ASCII,
	"TEXT"               Long ASCII,
	"BILD_NAME"               Varchar (100) ASCII,
	"BILD_TYPE"               Varchar (120) ASCII,
	"BILD_SIZE"               Fixed (18,0),
	"BILD"               Char (2) ASCII,
	PRIMARY KEY ("ID")
)
//
insert into pressestimmen(id,title,headline,text,bild_name,bild_type,bild_size,bild)
values(1,'test','test','testtext','test','test/test',100000,'te')
//
insert into pressestimmen(id,title,headline,text,bild_name,bild_type,bild_size,bild)
values(2,'test','test','testtext','test','test/test',100000,'te')
//
insert into pressestimmen(id,title,headline,text,bild_name,bild_type,bild_size,bild)
values(2,'test','test','testtext','test','test/test',100000,'te')

3)
run the following php script (my unixODBC instance is called "OLTP"):

<?

$dbcon = odbc_connect ("OLTP", "CRASHTEST", "CRASHTEST");

$z=odbc_exec("select * from pressestimmen where id=3");
$a = odbc_exec ($dbcon, "select id from pressestimmen");
echo "end of script";flush();
?>

this crashes, and the gdb backtrace is:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 47129735329440 (LWP 15483)]
0x00002add3ea84f01 in _int_malloc () from /lib64/libc.so.6
(gdb) bt
#0  0x00002add3ea84f01 in _int_malloc () from /lib64/libc.so.6
#1  0x00002add3ea86d76 in malloc () from /lib64/libc.so.6
#2  0x00002add413c20cb in _emalloc (size=21) at /usr/src/php4-STABLE-200612061330/Zend/zend_alloc.c:177
#3  0x00002add4132277a in odbc_bindcols (result=0x555555b26668) at /usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c:674
#4  0x00002add41325c0f in zif_odbc_exec (ht=<value optimized out>, return_value=0x555555b25188, this_ptr=<value optimized out>,
    return_value_used=<value optimized out>) at /usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c:1323
#5  0x00002add413eb1ce in execute (op_array=0x555555b20478) at /usr/src/php4-STABLE-200612061330/Zend/zend_execute.c:1681
#6  0x00002add413d1a9a in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/php4-STABLE-200612061330/Zend/zend.c:935
#7  0x00002add413a34b7 in php_execute_script (primary_file=0x7fff6d02ba50) at /usr/src/php4-STABLE-200612061330/main/main.c:1752
#8  0x00002add413ef83d in php_handler (r=0x555555b0d0a8) at /usr/src/php4-STABLE-200612061330/sapi/apache2handler/sapi_apache2.c:581
#9  0x000055555558c6ba in ap_run_handler () from /usr/sbin/httpd2-prefork
#10 0x000055555558faa2 in ap_invoke_handler () from /usr/sbin/httpd2-prefork
#11 0x000055555559a1c8 in ap_process_request () from /usr/sbin/httpd2-prefork
#12 0x0000555555597409 in ap_register_input_filter () from /usr/sbin/httpd2-prefork
#13 0x0000555555593772 in ap_run_process_connection () from /usr/sbin/httpd2-prefork
#14 0x000055555559dc09 in ap_graceful_stop_signalled () from /usr/sbin/httpd2-prefork
#15 0x000055555559de0e in ap_graceful_stop_signalled () from /usr/sbin/httpd2-prefork
#16 0x000055555559e911 in ap_mpm_run () from /usr/sbin/httpd2-prefork
#17 0x0000555555579cb8 in main () from /usr/sbin/httpd2-prefork
(gdb)

it crashes in the second call to odbc_exec. when I place a

echo "1";exit; between both calls to odbc_exec, the "1" is displayed and it does not crash.
 [2006-12-07 01:33 UTC] tobias dot barth at web-arts dot com
P.S.: inserting the third line with id 3:
insert into pressestimmen(id,title,headline,text,bild_name,bild_type,bild_size,bild)
values(3,'test','test','testtext','test','test/test',100000,'te')

causes the same crash ;)
 [2006-12-09 02:44 UTC] tobias dot barth at web-arts dot com
I reviewed the compiler output when compiling php_odbc.c today, and I saw the following warnings:

/usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c: In function 'zif_odbc_execute':
/usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c:1042: warning: cast to pointer from integer of different size
/usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c: In function 'zif_odbc_cursor':
/usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c:1157: warning: cast from pointer to integer of different size
/usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c: In function 'odbc_do_connect':
/usr/src/php4-STABLE-200612061330/ext/odbc/php_odbc.c:2302: warning: cast from pointer to integer of different size

In line 1042, you use the field "fp" as if it was a pointer:
rc = SQLBindParameter(result->stmt, (UWORD)i, SQL_PARAM_INPUT,
									  ctype, sqltype, precision, scale,
									  (void *)params[i-1].fp, 0,
									  &params[i-1].vallen);

on 32 Bit-Machines that may work, on 64 Bit machines, where the field "fp" is declared as "int" (which is 32 Bit on SuSE Linux 10.1), and a void* is a 64 Bit-Pointer, that will not work. 


In line 2302, you do it the other way:
			conn_id = (int)index_ptr->ptr;

Here, a pointer ("ptr") is treated as if it was an int value - cutting off the high 32 bits.

In line 1157, there is:
				sprintf(cursorname,"php_curs_%d", (int)result->stmt);

maybe "stmt" is chopped off here, too - maybe that is harmful, too.

I think those "treat int as if a pointer would fit into it" things could be the reason why I get those crashes after having used "odbc_exec" or other php_odbc functions - do you agree?

Greetings,

Tobias Barth
 [2007-04-28 19:56 UTC] tobias dot barth at web-arts dot com
I know a bit more about it now. Trying to do select queries on MaxDB tables with the unixODBC-Tool "isql" only returned the first column of the first row full with data, the rest was empty. I contacted the author of unixODBC, Nick Gorham, and was told to get the latest snapshot of unixODBC. With that snapshot, isql works. The reason: In 64 Bit systems, length parameters and pointers are 64-Bit. There is a new symbol "SQLLEN" in the header files of unixODBC now. But the problem persists in php. I got the latest php6 snapshot and got many compilation warnings in php_odbc.c because of incompatible pointer types. php_odbc.c uses SDWORD as length attributes and int variables as numeric representation of pointers - e.g. for creating connection names. I tried to fix that and put SQLLEN in each data structure where 4 byte datatypes where used and produces a compiler warning - now the warnings are gone. But I still get glibc errors, when doing select queries in MaxDB:

*** glibc detected *** /usr/sbin/httpd2-prefork: free(): invalid pointer: 0x00005555560c3e90 ***
*** glibc detected *** /usr/sbin/httpd2-prefork: free(): invalid pointer: 0x00005555560609c0 ***
*** glibc detected *** /usr/sbin/httpd2-prefork: free(): invalid pointer: 0x000055555605e660 ***
*** glibc detected *** /usr/sbin/httpd2-prefork: free(): invalid pointer: 0x0000555556052700 ***
*** glibc detected *** /usr/sbin/httpd2-prefork: free(): invalid pointer: 0x0000555556064400 ***
*** glibc detected *** /usr/sbin/httpd2-prefork: free(): invalid pointer: 0x00005555560cad60 ***

Perhaps I did something wrong with those SQLLEN things or just did not enough - would you please take a look at it?
The diff between the snapshot and my modified version is:

lxdevel:/usr/src/php6.0-200704281030/ext/odbc # diff -u php_odbc.c /tmp/php6.0-200704281030/ext/odbc/php_odbc.c
--- php_odbc.c  2007-04-28 15:23:07.000000000 +0200
+++ /tmp/php6.0-200704281030/ext/odbc/php_odbc.c        2007-03-13 02:30:20.000000000 +0100
@@ -642,7 +642,7 @@
        RETCODE rc;
        int i;
        SWORD       colnamelen; /* Not used */
-       SQLLEN      displaysize;
+       SDWORD      displaysize;

        result->values = (odbc_result_value *) safe_emalloc(sizeof(odbc_result_value), result->numcols, 0);

@@ -736,7 +736,7 @@
         */
        SDWORD len;
 #else
-       SQLLEN len;
+       SQLINTEGER len;
 #endif
        zval **pv_res, **pv_num;

@@ -932,15 +932,15 @@
 {
        zval **pv_res, **pv_param_arr, **tmp;
        typedef struct params_t {
-               SQLLEN vallen;
-               SQLLEN fp;
+               SDWORD vallen;
+               int fp;
        } params_t;
        params_t *params = NULL;
        char *filename;
        unsigned char otype;
        SWORD sqltype, ctype, scale;
        SWORD nullable;
-       SQLLEN precision;
+       UDWORD precision;
        odbc_result   *result;
        int numArgs, i, ne;
        RETCODE rc;
@@ -1154,7 +1154,7 @@
                                                result->stmt, state, &error, errormsg,
                                                sizeof(errormsg)-1, &errormsgsize);
                        if (!strncmp(state,"S1015",5)) {
-                               snprintf(cursorname, max_len+1, "php_curs_%d", (SQLLEN)result->stmt);
+                               snprintf(cursorname, max_len+1, "php_curs_%d", (int)result->stmt);
                                if (SQLSetCursorName(result->stmt,cursorname,SQL_NTS) != SQL_SUCCESS) {
                                        odbc_sql_error(result->conn_ptr, result->stmt, "SQLSetCursorName");
                                        RETVAL_FALSE;
@@ -1726,7 +1726,7 @@
        odbc_result *result;
        int i = 0;
        RETCODE rc;
-       SQLLEN  fieldsize;
+       SDWORD  fieldsize;
        zval **pv_res, **pv_field;
 #ifdef HAVE_SQL_EXTENDED_FETCH
        UDWORD crow;
@@ -2334,13 +2334,12 @@

                if (zend_hash_find(&EG(regular_list), hashed_details, hashed_len + 1,
                                        (void **) &index_ptr) == SUCCESS) {
-                       int type;
-                       SQLLEN conn_id;
+                       int type, conn_id;
                        void *ptr;
                        if (Z_TYPE_P(index_ptr) != le_index_ptr) {
                                RETURN_FALSE;
                        }
-                       conn_id = (SQLLEN)index_ptr->ptr;
+                       conn_id = (int)index_ptr->ptr;
                        ptr = zend_list_find(conn_id, &type);   /* check if the connection is still there */
                        if (ptr && (type == le_conn || type == le_pconn)) {
                                zend_list_addref(conn_id);
@@ -2426,7 +2425,7 @@
 PHP_FUNCTION(odbc_num_rows)
 {
        odbc_result *result;
-       SQLROWCOUNT rows;
+       SDWORD rows;
        zval **pv_res;

        if (zend_get_parameters_ex(1, &pv_res) == FAILURE) {
lxdevel:/usr/src/php6.0-200704281030/ext/odbc # diff -u /tmp/php6.0-200704281030/ext/odbc/php_odbc.c php_oodbc.c
diff: php_oodbc.c: Datei oder Verzeichnis nicht gefunden
lxdevel:/usr/src/php6.0-200704281030/ext/odbc # diff -u /tmp/php6.0-200704281030/ext/odbc/php_odbc.c php_odbc.c
--- /tmp/php6.0-200704281030/ext/odbc/php_odbc.c        2007-03-13 02:30:20.000000000 +0100
+++ php_odbc.c  2007-04-28 15:23:07.000000000 +0200
@@ -642,7 +642,7 @@
        RETCODE rc;
        int i;
        SWORD       colnamelen; /* Not used */
-       SDWORD      displaysize;
+       SQLLEN      displaysize;

        result->values = (odbc_result_value *) safe_emalloc(sizeof(odbc_result_value), result->numcols, 0);

@@ -736,7 +736,7 @@
         */
        SDWORD len;
 #else
-       SQLINTEGER len;
+       SQLLEN len;
 #endif
        zval **pv_res, **pv_num;

@@ -932,15 +932,15 @@
 {
        zval **pv_res, **pv_param_arr, **tmp;
        typedef struct params_t {
-               SDWORD vallen;
-               int fp;
+               SQLLEN vallen;
+               SQLLEN fp;
        } params_t;
        params_t *params = NULL;
        char *filename;
        unsigned char otype;
        SWORD sqltype, ctype, scale;
        SWORD nullable;
-       UDWORD precision;
+       SQLLEN precision;
        odbc_result   *result;
        int numArgs, i, ne;
        RETCODE rc;
@@ -1154,7 +1154,7 @@
                                                result->stmt, state, &error, errormsg,
                                                sizeof(errormsg)-1, &errormsgsize);
                        if (!strncmp(state,"S1015",5)) {
-                               snprintf(cursorname, max_len+1, "php_curs_%d", (int)result->stmt);
+                               snprintf(cursorname, max_len+1, "php_curs_%d", (SQLLEN)result->stmt);
                                if (SQLSetCursorName(result->stmt,cursorname,SQL_NTS) != SQL_SUCCESS) {
                                        odbc_sql_error(result->conn_ptr, result->stmt, "SQLSetCursorName");
                                        RETVAL_FALSE;
@@ -1726,7 +1726,7 @@
        odbc_result *result;
        int i = 0;
        RETCODE rc;
-       SDWORD  fieldsize;
+       SQLLEN  fieldsize;
        zval **pv_res, **pv_field;
 #ifdef HAVE_SQL_EXTENDED_FETCH
        UDWORD crow;
@@ -2334,12 +2334,13 @@

                if (zend_hash_find(&EG(regular_list), hashed_details, hashed_len + 1,
                                        (void **) &index_ptr) == SUCCESS) {
-                       int type, conn_id;
+                       int type;
+                       SQLLEN conn_id;
                        void *ptr;
                        if (Z_TYPE_P(index_ptr) != le_index_ptr) {
                                RETURN_FALSE;
                        }
-                       conn_id = (int)index_ptr->ptr;
+                       conn_id = (SQLLEN)index_ptr->ptr;
                        ptr = zend_list_find(conn_id, &type);   /* check if the connection is still there */
                        if (ptr && (type == le_conn || type == le_pconn)) {
                                zend_list_addref(conn_id);
@@ -2425,7 +2426,7 @@
 PHP_FUNCTION(odbc_num_rows)
 {
        odbc_result *result;
-       SDWORD rows;
+       SQLROWCOUNT rows;
        zval **pv_res;

        if (zend_get_parameters_ex(1, &pv_res) == FAILURE) {
lxdevel:/usr/src/php6.0-200704281030/ext/odbc #
 [2009-04-27 16:00 UTC] jani@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/


 [2009-05-05 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2009-08-18 12:02 UTC] tobias dot barth at web-arts dot com
works for me with php 5.2.10.
 [2010-06-21 00:27 UTC] felipe@php.net
-Status: Open +Status: Closed -PHP Version: 6CVS-2007-04-28 (snap) +PHP Version: 5.2 -Assigned To: +Assigned To: felipe
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon May 06 09:01:30 2024 UTC