fix possible invalid free and a leak
[m6w6/ext-pq] / src / php_pqtypes.c
index fc9a16e19a4ec8cc6451104e90a8c1b1f7950c63..e5733da650d748a76a0b39336ea85ab2eda78f0a 100644 (file)
@@ -136,6 +136,7 @@ static int php_pqtypes_object_has_dimension(zval *object, zval *member, int chec
                                        return Z_TYPE_PP(data) != IS_NULL;
                                }
                                efree(key_str);
+                               key_str = NULL;
                        } else {
                                if (SUCCESS == zend_hash_index_find(&obj->intern->types, index, (void *) &data)) {
                                        return Z_TYPE_PP(data) != IS_NULL;
@@ -172,9 +173,10 @@ static zval *php_pqtypes_object_read_dimension(zval *object, zval *member, int t
                                return *data;
                        }
                }
-               if (key_str) {
-                       efree(key_str);
-               }
+       }
+
+       if (key_str) {
+               efree(key_str);
        }
 
        return NULL;
@@ -225,7 +227,32 @@ static PHP_METHOD(pqtypes, __construct) {
        "from pg_type t join pg_namespace n on t.typnamespace=n.oid " \
        "where typisdefined " \
        "and typrelid=0"
-#define PHP_PQ_OID_TEXT 25
+#ifndef PHP_PQ_OID_TEXT
+# define PHP_PQ_OID_TEXT 25
+#endif
+
+static int apply_nsp(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
+{
+       zval **zp = p;
+       unsigned pcount, tcount;
+       php_pq_params_t *params = va_arg(argv, php_pq_params_t *);
+       smart_str *str = va_arg(argv, smart_str *);
+
+       tcount = php_pq_params_add_type_oid(params, PHP_PQ_OID_TEXT);
+       pcount = php_pq_params_add_param(params, *zp);
+
+       if (tcount != pcount) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Param/Type count mismatch");
+               return ZEND_HASH_APPLY_STOP;
+       }
+       if (pcount > 1) {
+               smart_str_appendc(str, ',');
+       }
+       smart_str_appendc(str, '$');
+       smart_str_append_unsigned(str, pcount);
+
+       return ZEND_HASH_APPLY_KEEP;
+}
 
 ZEND_BEGIN_ARG_INFO_EX(ai_pqtypes_refresh, 0, 0, 0)
        ZEND_ARG_ARRAY_INFO(0, namespaces, 1)
@@ -250,33 +277,18 @@ static PHP_METHOD(pqtypes, refresh) {
                        if (!nsp || !zend_hash_num_elements(nsp)) {
                                res = PQexec(obj->intern->conn->intern->conn, PHP_PQ_TYPES_QUERY " and nspname in ('public', 'pg_catalog')");
                        } else {
-                               int i, count;
-                               Oid *oids;
-                               char **params = NULL;
-                               HashTable zdtor;
                                smart_str str = {0};
+                               php_pq_params_t *params = php_pq_params_init(&obj->intern->conn->intern->converters, NULL, NULL TSRMLS_CC);
 
                                smart_str_appends(&str, PHP_PQ_TYPES_QUERY " and nspname in(");
-                               zend_hash_init(&zdtor, 0, NULL, ZVAL_PTR_DTOR, 0);
-                               count = php_pq_params_to_array(nsp, &params, &zdtor TSRMLS_CC);
-                               oids = ecalloc(count + 1, sizeof(*oids));
-                               for (i = 0; i < count; ++i) {
-                                       oids[i] = PHP_PQ_OID_TEXT;
-                                       if (i) {
-                                               smart_str_appendc(&str, ',');
-                                       }
-                                       smart_str_appendc(&str, '$');
-                                       smart_str_append_unsigned(&str, i+1);
-                               }
+                               zend_hash_apply_with_arguments(nsp TSRMLS_CC, apply_nsp, 2, params, &str);
                                smart_str_appendc(&str, ')');
                                smart_str_0(&str);
 
-                               res = PQexecParams(obj->intern->conn->intern->conn, str.c, count, oids, (const char *const*) params, NULL, NULL, 0);
+                               res = PQexecParams(obj->intern->conn->intern->conn, str.c, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
 
                                smart_str_free(&str);
-                               efree(oids);
-                               efree(params);
-                               zend_hash_destroy(&zdtor);
+                               php_pq_params_free(&params);
                        }
 
                        if (!res) {
@@ -293,7 +305,7 @@ static PHP_METHOD(pqtypes, refresh) {
                                                Z_ADDREF_P(row);
 
                                                zend_hash_index_update(&obj->intern->types, oid, (void *) &row, sizeof(zval *), NULL);
-                                               zend_hash_add(&obj->intern->types, name, strlen(name) + 1, (void *) &row, sizeof(zval *), NULL);
+                                               zend_hash_update(&obj->intern->types, name, strlen(name) + 1, (void *) &row, sizeof(zval *), NULL);
                                        }
                                }
 
@@ -310,6 +322,12 @@ static zend_function_entry php_pqtypes_methods[] = {
        {0}
 };
 
+PHP_MSHUTDOWN_FUNCTION(pqtypes)
+{
+       zend_hash_destroy(&php_pqtypes_object_prophandlers);
+       return SUCCESS;
+}
+
 PHP_MINIT_FUNCTION(pqtypes)
 {
        zend_class_entry ce = {0};
@@ -324,6 +342,8 @@ PHP_MINIT_FUNCTION(pqtypes)
        php_pqtypes_object_handlers.write_property = php_pq_object_write_prop;
        php_pqtypes_object_handlers.clone_obj = NULL;
        php_pqtypes_object_handlers.get_property_ptr_ptr = NULL;
+       php_pqtypes_object_handlers.get_gc = NULL;
+       php_pqtypes_object_handlers.get_properties = php_pq_object_properties;
        php_pqtypes_object_handlers.get_debug_info = php_pq_object_debug_info;
        php_pqtypes_object_handlers.has_dimension = php_pqtypes_object_has_dimension;
        php_pqtypes_object_handlers.read_dimension = php_pqtypes_object_read_dimension;
@@ -336,6 +356,15 @@ PHP_MINIT_FUNCTION(pqtypes)
        ph.read = php_pqtypes_object_read_connection;
        zend_hash_add(&php_pqtypes_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
 
+#ifdef HAVE_PHP_PQ_TYPE_H
+#      undef PHP_PQ_TYPE
+#      define PHP_PQ_TYPE(name, oid) zend_declare_class_constant_long(php_pqtypes_class_entry, ZEND_STRL(name), oid TSRMLS_CC);
+#      include "php_pq_type.h"
+       zend_declare_class_constant_bool(php_pqtypes_class_entry, ZEND_STRL("DEFINED"), 1 TSRMLS_CC);
+#else
+       zend_declare_class_constant_bool(php_pqtypes_class_entry, ZEND_STRL("DEFINED"), 0 TSRMLS_CC);
+#endif
+
        return SUCCESS;
 }