@@ -3269,8 +3269,14 @@ PHP_FUNCTION(pg_escape_string)
32693269
32703270 to = zend_string_safe_alloc(ZSTR_LEN(from), 2, 0, 0);
32713271 if (link) {
3272+ int err;
32723273 pgsql = link->conn;
3273- ZSTR_LEN(to) = PQescapeStringConn(pgsql, ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from), NULL);
3274+ ZSTR_LEN(to) = PQescapeStringConn(pgsql, ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from), &err);
3275+ if (err) {
3276+ zend_argument_value_error(ZEND_NUM_ARGS(), "Escaping string failed");
3277+ zend_string_efree(to);
3278+ RETURN_THROWS();
3279+ }
32743280 } else
32753281 {
32763282 ZSTR_LEN(to) = PQescapeString(ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from));
@@ -3313,6 +3319,10 @@ PHP_FUNCTION(pg_escape_bytea)
33133319 } else {
33143320 to = (char *)PQescapeBytea((unsigned char *)ZSTR_VAL(from), ZSTR_LEN(from), &to_len);
33153321 }
3322+ if (to == NULL) {
3323+ zend_argument_value_error(ZEND_NUM_ARGS(), "Escape failure");
3324+ RETURN_THROWS();
3325+ }
33163326
33173327 RETVAL_STRINGL(to, to_len-1); /* to_len includes additional '\0' */
33183328 PQfreemem(to);
@@ -4245,7 +4255,7 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string
42454255 char *escaped;
42464256 smart_str querystr = {0};
42474257 size_t new_len;
4248- int i, num_rows;
4258+ int i, num_rows, err ;
42494259 zval elem;
42504260
42514261 ZEND_ASSERT(ZSTR_LEN(table_name) != 0);
@@ -4283,15 +4293,29 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string
42834293 "WHERE a.attnum > 0 AND c.relname = '");
42844294 }
42854295 escaped = (char *)safe_emalloc(strlen(tmp_name2), 2, 1);
4286- new_len = PQescapeStringConn(pg_link, escaped, tmp_name2, strlen(tmp_name2), NULL);
4296+ new_len = PQescapeStringConn(pg_link, escaped, tmp_name2, strlen(tmp_name2), &err);
4297+ if (err) {
4298+ php_error_docref(NULL, E_WARNING, "Escaping table name '%s' failed", ZSTR_VAL(table_name));
4299+ efree(src);
4300+ efree(escaped);
4301+ smart_str_free(&querystr);
4302+ return FAILURE;
4303+ }
42874304 if (new_len) {
42884305 smart_str_appendl(&querystr, escaped, new_len);
42894306 }
42904307 efree(escaped);
42914308
42924309 smart_str_appends(&querystr, "' AND n.nspname = '");
42934310 escaped = (char *)safe_emalloc(strlen(tmp_name), 2, 1);
4294- new_len = PQescapeStringConn(pg_link, escaped, tmp_name, strlen(tmp_name), NULL);
4311+ new_len = PQescapeStringConn(pg_link, escaped, tmp_name, strlen(tmp_name), &err);
4312+ if (err) {
4313+ php_error_docref(NULL, E_WARNING, "Escaping table namespace '%s' failed", ZSTR_VAL(table_name));
4314+ efree(src);
4315+ efree(escaped);
4316+ smart_str_free(&querystr);
4317+ return FAILURE;
4318+ }
42954319 if (new_len) {
42964320 smart_str_appendl(&querystr, escaped, new_len);
42974321 }
@@ -4552,7 +4576,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
45524576{
45534577 zend_string *field = NULL;
45544578 zval meta, *def, *type, *not_null, *has_default, *is_enum, *val, new_val;
4555- int err = 0, skip_field;
4579+ int err = 0, escape_err = 0, skip_field;
45564580 php_pgsql_data_type data_type;
45574581
45584582 ZEND_ASSERT(pg_link != NULL);
@@ -4804,8 +4828,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
48044828 /* PostgreSQL ignores \0 */
48054829 str = zend_string_alloc(Z_STRLEN_P(val) * 2, 0);
48064830 /* better to use PGSQLescapeLiteral since PGescapeStringConn does not handle special \ */
4807- ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str), Z_STRVAL_P(val), Z_STRLEN_P(val), NULL);
4808- ZVAL_STR(&new_val, php_pgsql_add_quotes(str));
4831+ ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str),
4832+ Z_STRVAL_P(val), Z_STRLEN_P(val), &escape_err);
4833+ if (escape_err) {
4834+ err = 1;
4835+ } else {
4836+ ZVAL_STR(&new_val, php_pgsql_add_quotes(str));
4837+ }
48094838 zend_string_release_ex(str, false);
48104839 }
48114840 break;
@@ -4828,7 +4857,14 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
48284857 }
48294858 PGSQL_CONV_CHECK_IGNORE();
48304859 if (err) {
4831- zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type));
4860+ if (escape_err) {
4861+ php_error_docref(NULL, E_NOTICE,
4862+ "String value escaping failed for PostgreSQL '%s' (%s)",
4863+ Z_STRVAL_P(type), ZSTR_VAL(field));
4864+ } else {
4865+ zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given",
4866+ get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type));
4867+ }
48324868 }
48334869 break;
48344870
@@ -5103,6 +5139,11 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
51035139 zend_string *tmp_zstr;
51045140
51055141 tmp = PQescapeByteaConn(pg_link, (unsigned char *)Z_STRVAL_P(val), Z_STRLEN_P(val), &to_len);
5142+ if (tmp == NULL) {
5143+ php_error_docref(NULL, E_NOTICE, "Escaping value failed for %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field));
5144+ err = 1;
5145+ break;
5146+ }
51065147 tmp_zstr = zend_string_init((char *)tmp, to_len - 1, false); /* PQescapeBytea's to_len includes additional '\0' */
51075148 PQfreemem(tmp);
51085149
@@ -5181,6 +5222,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
51815222 zend_hash_update(Z_ARRVAL_P(result), field, &new_val);
51825223 } else {
51835224 char *escaped = PQescapeIdentifier(pg_link, ZSTR_VAL(field), ZSTR_LEN(field));
5225+ if (escaped == NULL) {
5226+ /* This cannot fail because of invalid string but only due to failed memory allocation */
5227+ php_error_docref(NULL, E_NOTICE, "Escaping field '%s' failed", ZSTR_VAL(field));
5228+ err = 1;
5229+ break;
5230+ }
51845231 add_assoc_zval(result, escaped, &new_val);
51855232 PQfreemem(escaped);
51865233 }
@@ -5259,7 +5306,7 @@ static bool do_exec(smart_str *querystr, ExecStatusType expect, PGconn *pg_link,
52595306}
52605307/* }}} */
52615308
5262- static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const zend_string *table) /* {{{ */
5309+ static inline zend_result build_tablename(smart_str *querystr, PGconn *pg_link, const zend_string *table) /* {{{ */
52635310{
52645311 /* schema.table should be "schema"."table" */
52655312 const char *dot = memchr(ZSTR_VAL(table), '.', ZSTR_LEN(table));
@@ -5269,6 +5316,10 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z
52695316 smart_str_appendl(querystr, ZSTR_VAL(table), len);
52705317 } else {
52715318 char *escaped = PQescapeIdentifier(pg_link, ZSTR_VAL(table), len);
5319+ if (escaped == NULL) {
5320+ php_error_docref(NULL, E_NOTICE, "Failed to escape table name '%s'", ZSTR_VAL(table));
5321+ return FAILURE;
5322+ }
52725323 smart_str_appends(querystr, escaped);
52735324 PQfreemem(escaped);
52745325 }
@@ -5281,11 +5332,17 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z
52815332 smart_str_appendl(querystr, after_dot, len);
52825333 } else {
52835334 char *escaped = PQescapeIdentifier(pg_link, after_dot, len);
5335+ if (escaped == NULL) {
5336+ php_error_docref(NULL, E_NOTICE, "Failed to escape table name '%s'", ZSTR_VAL(table));
5337+ return FAILURE;
5338+ }
52845339 smart_str_appendc(querystr, '.');
52855340 smart_str_appends(querystr, escaped);
52865341 PQfreemem(escaped);
52875342 }
52885343 }
5344+
5345+ return SUCCESS;
52895346}
52905347/* }}} */
52915348
@@ -5306,7 +5363,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
53065363 ZVAL_UNDEF(&converted);
53075364 if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0) {
53085365 smart_str_appends(&querystr, "INSERT INTO ");
5309- build_tablename(&querystr, pg_link, table);
5366+ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
5367+ goto cleanup;
5368+ }
53105369 smart_str_appends(&querystr, " DEFAULT VALUES");
53115370
53125371 goto no_values;
@@ -5322,7 +5381,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
53225381 }
53235382
53245383 smart_str_appends(&querystr, "INSERT INTO ");
5325- build_tablename(&querystr, pg_link, table);
5384+ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
5385+ goto cleanup;
5386+ }
53265387 smart_str_appends(&querystr, " (");
53275388
53285389 ZEND_HASH_FOREACH_STR_KEY(Z_ARRVAL_P(var_array), fld) {
@@ -5332,6 +5393,10 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
53325393 }
53335394 if (opt & PGSQL_DML_ESCAPE) {
53345395 tmp = PQescapeIdentifier(pg_link, ZSTR_VAL(fld), ZSTR_LEN(fld) + 1);
5396+ if (tmp == NULL) {
5397+ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s'", ZSTR_VAL(fld));
5398+ goto cleanup;
5399+ }
53355400 smart_str_appends(&querystr, tmp);
53365401 PQfreemem(tmp);
53375402 } else {
@@ -5343,15 +5408,19 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
53435408 smart_str_appends(&querystr, ") VALUES (");
53445409
53455410 /* make values string */
5346- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(var_array), val) {
5411+ ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P(var_array), fld , val) {
53475412 /* we can avoid the key_type check here, because we tested it in the other loop */
53485413 switch (Z_TYPE_P(val)) {
53495414 case IS_STRING:
53505415 if (opt & PGSQL_DML_ESCAPE) {
5351- size_t new_len;
5352- char *tmp;
5353- tmp = (char *)safe_emalloc(Z_STRLEN_P(val), 2, 1);
5354- new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), NULL);
5416+ int error;
5417+ char *tmp = safe_emalloc(Z_STRLEN_P(val), 2, 1);
5418+ size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), &error);
5419+ if (error) {
5420+ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s' value", ZSTR_VAL(fld));
5421+ efree(tmp);
5422+ goto cleanup;
5423+ }
53555424 smart_str_appendc(&querystr, '\'');
53565425 smart_str_appendl(&querystr, tmp, new_len);
53575426 smart_str_appendc(&querystr, '\'');
@@ -5507,6 +5576,10 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
55075576 }
55085577 if (opt & PGSQL_DML_ESCAPE) {
55095578 char *tmp = PQescapeIdentifier(pg_link, ZSTR_VAL(fld), ZSTR_LEN(fld) + 1);
5579+ if (tmp == NULL) {
5580+ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s'", ZSTR_VAL(fld));
5581+ return -1;
5582+ }
55105583 smart_str_appends(querystr, tmp);
55115584 PQfreemem(tmp);
55125585 } else {
@@ -5522,8 +5595,14 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
55225595 switch (Z_TYPE_P(val)) {
55235596 case IS_STRING:
55245597 if (opt & PGSQL_DML_ESCAPE) {
5598+ int error;
55255599 char *tmp = (char *)safe_emalloc(Z_STRLEN_P(val), 2, 1);
5526- size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), NULL);
5600+ size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), &error);
5601+ if (error) {
5602+ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s' value", ZSTR_VAL(fld));
5603+ efree(tmp);
5604+ return -1;
5605+ }
55275606 smart_str_appendc(querystr, '\'');
55285607 smart_str_appendl(querystr, tmp, new_len);
55295608 smart_str_appendc(querystr, '\'');
@@ -5591,7 +5670,9 @@ PHP_PGSQL_API zend_result php_pgsql_update(PGconn *pg_link, const zend_string *t
55915670 }
55925671
55935672 smart_str_appends(&querystr, "UPDATE ");
5594- build_tablename(&querystr, pg_link, table);
5673+ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
5674+ goto cleanup;
5675+ }
55955676 smart_str_appends(&querystr, " SET ");
55965677
55975678 if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(var_array), 0, ",", 1, opt))
@@ -5694,7 +5775,9 @@ PHP_PGSQL_API zend_result php_pgsql_delete(PGconn *pg_link, const zend_string *t
56945775 }
56955776
56965777 smart_str_appends(&querystr, "DELETE FROM ");
5697- build_tablename(&querystr, pg_link, table);
5778+ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
5779+ goto cleanup;
5780+ }
56985781 smart_str_appends(&querystr, " WHERE ");
56995782
57005783 if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1, opt))
@@ -5834,7 +5917,9 @@ PHP_PGSQL_API zend_result php_pgsql_select(PGconn *pg_link, const zend_string *t
58345917 }
58355918
58365919 smart_str_appends(&querystr, "SELECT * FROM ");
5837- build_tablename(&querystr, pg_link, table);
5920+ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
5921+ goto cleanup;
5922+ }
58385923 smart_str_appends(&querystr, " WHERE ");
58395924
58405925 if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1, opt))
0 commit comments