ID:               39756
 Updated by:       [EMAIL PROTECTED]
 Reported By:      tobias dot barth at web-arts dot com
-Status:           Assigned
+Status:           Open
 Bug Type:         ODBC related
 Operating System: SuSE Linux 10.1
 PHP Version:      6.0 (snapshot 2007-04-28 10:30)
 Assigned To:      kalowsky


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

[2007-04-28 19:56:47] 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 #

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

[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

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

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