ID: 30280 Comment by: andreyra at chtivo dot ru Reported By: freddyz77 at tin dot it Status: Assigned Bug Type: MSSQL related Operating System: Any PHP Version: 4.3.9 Assigned To: fmk New Comment:
How to get the compiled version of this dll for Windows? Previous Comments: ------------------------------------------------------------------------ [2004-09-29 20:39:37] freddyz77 at tin dot it Description: ------------ Well, I wrote this patch just looking at the code, I hope someone find some useful info. Mainly it contains some memory leak fix connecting and some others minor issues and notes. --- php_mssql.c.orig 2004-09-29 19:52:42.000000000 +0200 +++ php_mssql.c 2004-09-29 20:29:10.000000000 +0200 @@ -197,20 +197,23 @@ result->data = NULL; result->blocks_initialized = 0; } if (free_fields && result->fields) { for (i=0; i<result->num_fields; i++) { STR_FREE(result->fields[i].name); STR_FREE(result->fields[i].column_source); } efree(result->fields); + result->fields = NULL; + result->num_fields = 0; + result->cur_field = 0; } } static void _free_mssql_statement(mssql_statement *statement) { if (statement->binds) { zend_hash_destroy(statement->binds); efree(statement->binds); } @@ -263,28 +266,25 @@ mssql_bind *bind= (mssql_bind *) data; zval_ptr_dtor(&(bind->zval)); } static void php_mssql_init_globals(zend_mssql_globals *mssql_globals) { long compatability_mode; mssql_globals->num_persistent = 0; + mssql_globals->get_column_content = php_mssql_get_column_content_with_type; if (cfg_get_long("mssql.compatability_mode", &compatability_mode) == SUCCESS) { if (compatability_mode) { mssql_globals->get_column_content = php_mssql_get_column_content_without_type; - } else { - mssql_globals->get_column_content = php_mssql_get_column_content_with_type; } - } else { - mssql_globals->get_column_content = php_mssql_get_column_content_with_type; } } PHP_MINIT_FUNCTION(mssql) { ZEND_INIT_MODULE_GLOBALS(mssql, php_mssql_init_globals, NULL); REGISTER_INI_ENTRIES(); le_statement = register_list_destructors(_free_mssql_statement, NULL); @@ -508,61 +508,68 @@ if (DBSETOPT(mssql.link, DBBUFFER, "2")==FAIL) { efree(hashed_details); dbfreelogin(mssql.login); dbclose(mssql.link); RETURN_FALSE; } if (MS_SQL_G(textlimit) != -1) { sprintf(buffer, "%li", MS_SQL_G(textlimit)); if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) { + dbclose(mssql.link); efree(hashed_details); dbfreelogin(mssql.login); RETURN_FALSE; } } if (MS_SQL_G(textsize) != -1) { sprintf(buffer, "SET TEXTSIZE %li", MS_SQL_G(textsize)); dbcmd(mssql.link, buffer); dbsqlexec(mssql.link); dbresults(mssql.link); } /* hash it up */ mssql_ptr = (mssql_link *) malloc(sizeof(mssql_link)); memcpy(mssql_ptr, &mssql, sizeof(mssql_link)); Z_TYPE(new_le) = le_plink; new_le.ptr = mssql_ptr; if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length + 1, &new_le, sizeof(list_entry), NULL)==FAILURE) { free(mssql_ptr); + dbclose(mssql.link); efree(hashed_details); dbfreelogin(mssql.login); RETURN_FALSE; } MS_SQL_G(num_persistent)++; MS_SQL_G(num_links)++; } else { /* we do */ + dbfreelogin(mssql.login); + if (Z_TYPE_P(le) != le_plink) { + efree(hashed_details); #if BROKEN_MSSQL_PCONNECTS log_error("PHP/MS SQL: Hashed persistent link is not a MS SQL link!",php_rqst->server); #endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Hashed persistent link is not a MS SQL link!"); RETURN_FALSE; } mssql_ptr = (mssql_link *) le->ptr; /* test that the link hasn't died */ if (DBDEAD(mssql_ptr->link) == TRUE) { + /* free previous connection */ + dbclose(mssql_ptr->link); #if BROKEN_MSSQL_PCONNECTS log_error("PHP/MS SQL: Persistent link died, trying to reconnect...",php_rqst->server); #endif - if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==FAIL) { + if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==NULL) { #if BROKEN_MSSQL_PCONNECTS log_error("PHP/MS SQL: Unable to reconnect!",php_rqst->server); #endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect"); zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1); efree(hashed_details); RETURN_FALSE; } #if BROKEN_MSSQL_PCONNECTS log_error("PHP/MS SQL: Reconnect successful!",php_rqst->server); @@ -584,57 +591,63 @@ /* first we check the hash for the hashed_details key. if it exists, * it should point us to the right offset where the actual mssql link sits. * if it doesn't, open a new mssql link, add it to the resource list, * and add a pointer to it with hashed_details as the key. */ if (zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length + 1,(void **) &index_ptr)==SUCCESS) { int type,link; void *ptr; if (Z_TYPE_P(index_ptr) != le_index_ptr) { + efree(hashed_details); + dbfreelogin(mssql.login); RETURN_FALSE; } link = (int) index_ptr->ptr; ptr = zend_list_find(link,&type); /* check if the link is still there */ if (ptr && (type==le_link || type==le_plink)) { zend_list_addref(link); Z_LVAL_P(return_value) = link; php_mssql_set_default_link(link TSRMLS_CC); Z_TYPE_P(return_value) = IS_RESOURCE; efree(hashed_details); + dbfreelogin(mssql.login); return; } else { zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length + 1); } } if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links)); efree(hashed_details); + dbfreelogin(mssql.login); RETURN_FALSE; } if ((mssql.link=dbopen(mssql.login, host))==NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", host); efree(hashed_details); + dbfreelogin(mssql.login); RETURN_FALSE; } if (DBSETOPT(mssql.link, DBBUFFER,"2")==FAIL) { efree(hashed_details); dbfreelogin(mssql.login); dbclose(mssql.link); RETURN_FALSE; } if (MS_SQL_G(textlimit) != -1) { sprintf(buffer, "%li", MS_SQL_G(textlimit)); if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) { + dbclose(mssql.link); efree(hashed_details); dbfreelogin(mssql.login); RETURN_FALSE; } } if (MS_SQL_G(textsize) != -1) { sprintf(buffer, "SET TEXTSIZE %li", MS_SQL_G(textsize)); dbcmd(mssql.link, buffer); dbsqlexec(mssql.link); dbresults(mssql.link); @@ -980,40 +993,42 @@ type = dbrettype(mssql_ptr->link, i); if (statement->binds != NULL) { /* Maybe a non-parameter sp */ if (zend_hash_find(statement->binds, parameter, strlen(parameter), (void**)&bind)==SUCCESS) { switch (type) { case SQLBIT: case SQLINT1: case SQLINT2: case SQLINT4: convert_to_long_ex(&bind->zval); + /* FIXME this works only on little endian machine !!! */ Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i))); break; case SQLFLT4: case SQLFLT8: case SQLFLTN: case SQLMONEY4: case SQLMONEY: case SQLMONEYN: convert_to_double_ex(&bind->zval); Z_DVAL_P(bind->zval) = *((double *)(dbretdata(mssql_ptr->link,i))); break; case SQLCHAR: case SQLVARCHAR: case SQLTEXT: convert_to_string_ex(&bind->zval); Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i); Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval)); break; + /* TODO binary */ } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "An output parameter variable was not provided"); } } } } if (statement->binds != NULL) { /* Maybe a non-parameter sp */ if (zend_hash_find(statement->binds, "RETVAL", 6, (void**)&bind)==SUCCESS) { @@ -1187,40 +1202,44 @@ } if (dbsqlexec(mssql_ptr->link)==FAIL || (retvalue = dbresults(mssql_ptr->link))==FAIL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed"); RETURN_FALSE; } /* Skip results not returning any columns */ while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retvalue == SUCCEED) { retvalue = dbresults(mssql_ptr->link); } + if (retvalue != SUCCEED) { + RETURN_FALSE; + } if ((num_fields = dbnumcols(mssql_ptr->link)) <= 0) { RETURN_TRUE; } retvalue=dbnextrow(mssql_ptr->link); if (retvalue==FAIL) { RETURN_FALSE; } result = (mssql_result *) emalloc(sizeof(mssql_result)); result->statement = NULL; result->num_fields = num_fields; result->blocks_initialized = 1; result->batchsize = batchsize; result->data = NULL; result->blocks_initialized = 0; result->mssql_ptr = mssql_ptr; result->cur_field=result->cur_row=result->num_rows=0; + /* TODO here this condition it's always true */ if (num_fields > 0) { result->fields = (mssql_field *) emalloc(sizeof(mssql_field)*result->num_fields); result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC); } else result->fields = NULL; ZEND_REGISTER_RESOURCE(return_value, result, le_result); } /* }}} */ @@ -1267,20 +1286,21 @@ zend_list_delete(Z_RESVAL_PP(mssql_result_index)); RETURN_TRUE; } /* }}} */ /* {{{ proto string mssql_get_last_message(void) Gets the last message from the MS-SQL server */ PHP_FUNCTION(mssql_get_last_message) { + /* TODO add link parameter */ if (MS_SQL_G(server_message)) { RETURN_STRING(MS_SQL_G(server_message),1); } else { RETURN_STRING(empty_string,1); } } /* }}} */ @@ -2236,27 +2256,29 @@ convert_to_string_ex(binary); convert_to_long_ex(short_format); sf = Z_LVAL_PP(short_format); break; default: WRONG_PARAM_COUNT; break; } + /* FIXME this code can cause a buffer reading overflow if binary it's less than 16 bytes */ dbconvert(NULL, SQLBINARY, (BYTE*)Z_STRVAL_PP(binary), 16, SQLCHAR, buffer, -1); if (sf) { php_strtoupper(buffer, 32); RETURN_STRING(buffer, 1); } else { + /* FIXME this works only on little endian machine */ int i; for (i=0; i<4; i++) { buffer2[2*i] = buffer[6-2*i]; buffer2[2*i+1] = buffer[7-2*i]; } buffer2[8] = '-'; for (i=0; i<2; i++) { buffer2[9+2*i] = buffer[10-2*i]; buffer2[10+2*i] = buffer[11-2*i]; } ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=30280&edit=1