From 6d052b30f3d433cf741959907608268e8b45150c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 30 Sep 2020 10:06:51 +0200 Subject: [PATCH 1/5] Don't separate array parameter --- ext/odbc/php_odbc.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index d058fd0191d2e..1bf29fa1e1e19 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -977,7 +977,7 @@ PHP_FUNCTION(odbc_execute) int i, ne; RETCODE rc; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|h/", &pv_res, &pv_param_ht) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|h", &pv_res, &pv_param_ht) == FAILURE) { RETURN_THROWS(); } @@ -991,27 +991,16 @@ PHP_FUNCTION(odbc_execute) RETURN_FALSE; } - zend_hash_internal_pointer_reset(pv_param_ht); params = (params_t *)safe_emalloc(sizeof(params_t), result->numparams, 0); for(i = 0; i < result->numparams; i++) { params[i].fp = -1; } - for(i = 1; i <= result->numparams; i++) { - if ((tmp = zend_hash_get_current_data(pv_param_ht)) == NULL) { - php_error_docref(NULL, E_WARNING,"Error getting parameter"); - SQLFreeStmt(result->stmt,SQL_RESET_PARAMS); - for (i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } - efree(params); - RETURN_FALSE; - } - + i = 1; + ZEND_HASH_FOREACH_VAL(pv_param_ht, tmp) { + zend_string *tmpstr = zval_try_get_string(tmp); otype = Z_TYPE_P(tmp); - if (!try_convert_to_string(tmp)) { + if (!tmpstr) { SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); for (i = 0; i < result->numparams; i++) { if (params[i].fp != -1) { @@ -1022,7 +1011,7 @@ PHP_FUNCTION(odbc_execute) RETURN_THROWS(); } - params[i-1].vallen = Z_STRLEN_P(tmp); + params[i-1].vallen = ZSTR_LEN(tmpstr); params[i-1].fp = -1; if (IS_SQL_BINARY(result->param_info[i-1].sqltype)) { @@ -1031,14 +1020,15 @@ PHP_FUNCTION(odbc_execute) ctype = SQL_C_CHAR; } - if (Z_STRLEN_P(tmp) > 2 && - Z_STRVAL_P(tmp)[0] == '\'' && - Z_STRVAL_P(tmp)[Z_STRLEN_P(tmp) - 1] == '\'') { + if (ZSTR_LEN(tmpstr) > 2 && + ZSTR_VAL(tmpstr)[0] == '\'' && + ZSTR_VAL(tmpstr)[ZSTR_LEN(tmpstr) - 1] == '\'') { - if (CHECK_ZVAL_NULL_PATH(tmp)) { + if (ZSTR_LEN(tmpstr) != strlen(ZSTR_VAL(tmpstr))) { + zend_string_release(tmpstr); RETURN_FALSE; } - filename = estrndup(&Z_STRVAL_P(tmp)[1], Z_STRLEN_P(tmp) - 2); + filename = estrndup(&ZSTR_VAL(tmpstr)[1], ZSTR_LEN(tmpstr) - 2); filename[strlen(filename)] = '\0'; /* Check the basedir */ @@ -1050,6 +1040,7 @@ PHP_FUNCTION(odbc_execute) close(params[i].fp); } } + zend_string_release(tmpstr); efree(params); RETURN_FALSE; } @@ -1062,6 +1053,7 @@ PHP_FUNCTION(odbc_execute) close(params[i].fp); } } + zend_string_release(tmpstr); efree(params); efree(filename); RETURN_FALSE; @@ -1085,7 +1077,7 @@ PHP_FUNCTION(odbc_execute) rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT, ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale, - Z_STRVAL_P(tmp), 0, + ZSTR_VAL(tmpstr), 0, ¶ms[i-1].vallen); } if (rc == SQL_ERROR) { @@ -1096,11 +1088,13 @@ PHP_FUNCTION(odbc_execute) close(params[i].fp); } } + zend_string_release(tmpstr); efree(params); RETURN_FALSE; } - zend_hash_move_forward(pv_param_ht); - } + zend_string_release(tmpstr); + if (++i > result->numparams) break; + } ZEND_HASH_FOREACH_END(); } /* Close cursor, needed for doing multiple selects */ rc = SQLFreeStmt(result->stmt, SQL_CLOSE); From 992a41db2f782c3dbe9e4ecf7d96331f5b10fb2e Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 3 Oct 2020 13:26:57 +0200 Subject: [PATCH 2/5] Move otype declaration to inner scope --- ext/odbc/php_odbc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 1bf29fa1e1e19..6596fd5e9c0b5 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -971,9 +971,8 @@ PHP_FUNCTION(odbc_execute) } params_t; params_t *params = NULL; char *filename; - unsigned char otype; SQLSMALLINT ctype; - odbc_result *result; + odbc_result *result; int i, ne; RETCODE rc; @@ -998,8 +997,8 @@ PHP_FUNCTION(odbc_execute) i = 1; ZEND_HASH_FOREACH_VAL(pv_param_ht, tmp) { + unsigned char otype = Z_TYPE_P(tmp); zend_string *tmpstr = zval_try_get_string(tmp); - otype = Z_TYPE_P(tmp); if (!tmpstr) { SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); for (i = 0; i < result->numparams; i++) { From 7377df4a0e86b5e9e2d635ef15d65874959dc314 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 3 Oct 2020 13:34:13 +0200 Subject: [PATCH 3/5] Extract odbc_release_params() --- ext/odbc/php_odbc.c | 63 ++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 6596fd5e9c0b5..4fe2956ef301d 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -960,16 +960,27 @@ PHP_FUNCTION(odbc_prepare) * Execute prepared SQL statement. Supports only input parameters. */ +typedef struct odbc_params_t { + SQLLEN vallen; + int fp; +} odbc_params_t; + +static void odbc_release_params(odbc_result *result, odbc_params_t *params) { + SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); + for (int i = 0; i < result->numparams; i++) { + if (params[i].fp != -1) { + close(params[i].fp); + } + } + efree(params); +} + /* {{{ Execute a prepared statement */ PHP_FUNCTION(odbc_execute) { zval *pv_res, *tmp; HashTable *pv_param_ht = (HashTable *) &zend_empty_array; - typedef struct params_t { - SQLLEN vallen; - int fp; - } params_t; - params_t *params = NULL; + odbc_params_t *params = NULL; char *filename; SQLSMALLINT ctype; odbc_result *result; @@ -990,7 +1001,7 @@ PHP_FUNCTION(odbc_execute) RETURN_FALSE; } - params = (params_t *)safe_emalloc(sizeof(params_t), result->numparams, 0); + params = (odbc_params_t *)safe_emalloc(sizeof(odbc_params_t), result->numparams, 0); for(i = 0; i < result->numparams; i++) { params[i].fp = -1; } @@ -1000,13 +1011,7 @@ PHP_FUNCTION(odbc_execute) unsigned char otype = Z_TYPE_P(tmp); zend_string *tmpstr = zval_try_get_string(tmp); if (!tmpstr) { - SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); - for (i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } - efree(params); + odbc_release_params(result, params); RETURN_THROWS(); } @@ -1033,27 +1038,15 @@ PHP_FUNCTION(odbc_execute) /* Check the basedir */ if (php_check_open_basedir(filename)) { efree(filename); - SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); - for (i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } + odbc_release_params(result, params); zend_string_release(tmpstr); - efree(params); RETURN_FALSE; } if ((params[i-1].fp = open(filename,O_RDONLY)) == -1) { php_error_docref(NULL, E_WARNING,"Can't open file %s", filename); - SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); - for (i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } + odbc_release_params(result, params); zend_string_release(tmpstr); - efree(params); efree(filename); RETURN_FALSE; } @@ -1081,14 +1074,8 @@ PHP_FUNCTION(odbc_execute) } if (rc == SQL_ERROR) { odbc_sql_error(result->conn_ptr, result->stmt, "SQLBindParameter"); - SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); - for (i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } + odbc_release_params(result, params); zend_string_release(tmpstr); - efree(params); RETURN_FALSE; } zend_string_release(tmpstr); @@ -1131,13 +1118,7 @@ PHP_FUNCTION(odbc_execute) } if (result->numparams > 0) { - SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); - for(i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } - efree(params); + odbc_release_params(result, params); } if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA_FOUND) { From de399305bf5eb2d4a24f3fa89c5d4136c922d258 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 3 Oct 2020 13:37:01 +0200 Subject: [PATCH 4/5] Refactor if-else-switch to switch --- ext/odbc/php_odbc.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 4fe2956ef301d..3114f8bc9e4fe 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -1089,32 +1089,31 @@ PHP_FUNCTION(odbc_execute) odbc_sql_error(result->conn_ptr, result->stmt, "SQLFreeStmt"); } - rc = SQLExecute(result->stmt); - result->fetched = 0; - if (rc == SQL_NEED_DATA) { - char buf[4096]; - int fp, nbytes; - while (rc == SQL_NEED_DATA) { - rc = SQLParamData(result->stmt, (void*)&fp); - if (rc == SQL_NEED_DATA) { - while ((nbytes = read(fp, &buf, 4096)) > 0) { - SQLPutData(result->stmt, (void*)&buf, nbytes); + rc = SQLExecute(result->stmt); + switch (rc) { + case SQL_NEED_DATA: { + char buf[4096]; + int fp, nbytes; + while (rc == SQL_NEED_DATA) { + rc = SQLParamData(result->stmt, (void*)&fp); + if (rc == SQL_NEED_DATA) { + while ((nbytes = read(fp, &buf, 4096)) > 0) { + SQLPutData(result->stmt, (void*)&buf, nbytes); + } } } + break; } - } else { - switch (rc) { - case SQL_SUCCESS: - break; - case SQL_NO_DATA_FOUND: - case SQL_SUCCESS_WITH_INFO: - odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute"); - break; - default: - odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute"); - RETVAL_FALSE; - } + case SQL_SUCCESS: + break; + case SQL_NO_DATA_FOUND: + case SQL_SUCCESS_WITH_INFO: + odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute"); + break; + default: + odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute"); + RETVAL_FALSE; } if (result->numparams > 0) { From dcf2184ea6ad050a3aac4d4ee5b0adeffa8e307d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 3 Oct 2020 13:39:37 +0200 Subject: [PATCH 5/5] Release params on NUL bytes in path --- ext/odbc/php_odbc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 3114f8bc9e4fe..89d829c885521 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -1029,6 +1029,7 @@ PHP_FUNCTION(odbc_execute) ZSTR_VAL(tmpstr)[ZSTR_LEN(tmpstr) - 1] == '\'') { if (ZSTR_LEN(tmpstr) != strlen(ZSTR_VAL(tmpstr))) { + odbc_release_params(result, params); zend_string_release(tmpstr); RETURN_FALSE; }