Edit report at http://bugs.php.net/bug.php?id=39756&edit=1
ID: 39756 Updated by: [email protected] Reported by: tobias dot barth at web-arts dot com Summary: [PATCH] Crashes in fetching resultsets with LONG ASCII columns from MaxDB -Status: Open +Status: Closed Type: Bug Package: ODBC related Operating System: SuSE Linux 10.1 -PHP Version: 6CVS-2007-04-28 (snap) +PHP Version: 5.2 -Assigned To: +Assigned To: felipe Previous Comments: ------------------------------------------------------------------------ [2009-08-18 12:02:21] tobias dot barth at web-arts dot com works for me with php 5.2.10. ------------------------------------------------------------------------ [2009-05-05 01:00:01] 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-04-27 16:00:09] [email protected] Please try using this CVS snapshot: http://snaps.php.net/php5.2-latest.tar.gz For Windows: http://windows.php.net/snapshots/ ------------------------------------------------------------------------ [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, ¶ms[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/bug.php?id=39756 -- Edit this bug report at http://bugs.php.net/bug.php?id=39756&edit=1
