ID:               39756
 User updated by:  tobias dot barth at web-arts dot com
 Reported By:      tobias dot barth at web-arts dot com
 Status:           Assigned
 Bug Type:         ODBC related
 Operating System: SuSE Linux 10.1
-PHP Version:      4.4.4
+PHP Version:      6.0 (snapshot 2007-04-28 10:30)
 Assigned To:      kalowsky
 New Comment:

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 #


Previous Comments:
------------------------------------------------------------------------

[2006-12-09 02:44:47] 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

------------------------------------------------------------------------

[2006-12-07 09:23:09] [EMAIL PROTECTED]

Assigned to the maintainer.

------------------------------------------------------------------------

[2006-12-07 01:33:22] 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-07 01:10:43] 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-06 18:47:14] [EMAIL PROTECTED]

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).

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/39756

-- 
Edit this bug report at http://bugs.php.net/?id=39756&edit=1

Reply via email to