fix parameter separation
authorMichael Wallner <mike@php.net>
Wed, 1 Oct 2014 13:54:03 +0000 (15:54 +0200)
committerMichael Wallner <mike@php.net>
Wed, 1 Oct 2014 13:54:03 +0000 (15:54 +0200)
src/php_pq_params.c
src/php_pqstm.c

index 7208550a999d77fa025a5e23236fd20e7bb001fb..4a6ba68ca33ec8a42a7c77f3a4dcf03c37eef4b8 100644 (file)
@@ -113,9 +113,9 @@ static zval *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type TSR
                break;
 
        default:
-               SEPARATE_ZVAL(&zobj);
-               convert_to_string(zobj);
-               return_value = zobj;
+               MAKE_STD_ZVAL(return_value);
+               MAKE_COPY_ZVAL(&zobj, return_value);
+               convert_to_string(return_value);
                break;
        }
 
@@ -154,9 +154,16 @@ static int apply_to_param_from_array(void *ptr, void *arg_ptr TSRMLS_DC)
                ZVAL_LONG(ztype, arg->type);
                zend_call_method_with_2_params(arg->zconv, NULL, NULL, "converttostring", &rv, zcopy, ztype);
                zval_ptr_dtor(&ztype);
-               convert_to_string(rv);
-               zcopy = rv;
+
+               if (rv) {
+                       convert_to_string(rv);
+                       zcopy = rv;
+               } else {
+                       return ZEND_HASH_APPLY_STOP;
+               }
+
                goto append_string;
+
        } else {
                switch (Z_TYPE_P(zcopy)) {
                case IS_NULL:
@@ -213,7 +220,7 @@ static int apply_to_param_from_array(void *ptr, void *arg_ptr TSRMLS_DC)
 
 static zval *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type TSRMLS_DC)
 {
-       zval *return_value;
+       zval *zcopy, *return_value;
        smart_str s = {0};
        struct apply_to_param_from_array_arg arg = {NULL};
 
@@ -234,7 +241,10 @@ static zval *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type TSRM
                arg.type = PHP_PQ_TYPE_OF_ARRAY(type);
                zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type), (void *) &arg.zconv);
                smart_str_appendc(arg.buffer, '{');
-               zend_hash_apply_with_argument(Z_ARRVAL_P(zarr), apply_to_param_from_array, &arg TSRMLS_CC);
+               MAKE_STD_ZVAL(zcopy);
+               MAKE_COPY_ZVAL(&zarr, zcopy);
+               zend_hash_apply_with_argument(Z_ARRVAL_P(zcopy), apply_to_param_from_array, &arg TSRMLS_CC);
+               zval_ptr_dtor(&zcopy);
                smart_str_appendc(arg.buffer, '}');
                smart_str_0(&s);
                break;
@@ -265,9 +275,11 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **z
                ZVAL_LONG(ztype, type);
                zend_call_method_with_2_params(zconv, NULL, NULL, "converttostring", &rv, *zpp, ztype);
                zval_ptr_dtor(&ztype);
-               convert_to_string(rv);
-               p->param.strings[index] = Z_STRVAL_P(rv);
-               zend_hash_next_index_insert(&p->param.dtor, (void *) &rv, sizeof(zval *), NULL);
+               if (rv) {
+                       convert_to_string(rv);
+                       p->param.strings[index] = Z_STRVAL_P(rv);
+                       zend_hash_next_index_insert(&p->param.dtor, (void *) &rv, sizeof(zval *), NULL);
+               }
        } else {
                zval *tmp, *zcopy = *zpp;
 
@@ -281,13 +293,18 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **z
                        return;
 
                case IS_DOUBLE:
-                       SEPARATE_ZVAL(&zcopy);
+                       MAKE_STD_ZVAL(zcopy);
+                       MAKE_COPY_ZVAL(zpp, zcopy);
                        Z_TYPE_P(zcopy) = IS_STRING;
                        Z_STRLEN_P(zcopy) = spprintf(&Z_STRVAL_P(zcopy), 0, "%F", Z_DVAL_PP(zpp));
                        break;
 
                case IS_ARRAY:
-                       zcopy = array_param_to_string(p, zcopy, type TSRMLS_CC);
+                       MAKE_STD_ZVAL(zcopy);
+                       MAKE_COPY_ZVAL(zpp, zcopy);
+                       tmp = array_param_to_string(p, zcopy, type TSRMLS_CC);
+                       zval_ptr_dtor(&zcopy);
+                       zcopy = tmp;
                        break;
 
                case IS_OBJECT:
@@ -310,12 +327,17 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **z
        }
 }
 
-static int apply_to_params(void *zp TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
+struct apply_to_params_arg {
+       php_pq_params_t *params;
+       unsigned index;
+};
+
+static int apply_to_params(void *zp, void *arg_ptr TSRMLS_DC)
 {
-       php_pq_params_t *p = (php_pq_params_t *) va_arg(argv, php_pq_params_t *);
-       unsigned *index = (unsigned *) va_arg(argv, unsigned *);
+       struct apply_to_params_arg *arg = arg_ptr;
 
-       php_pq_params_set_param(p, (*index)++, zp);
+       SEPARATE_ZVAL_IF_NOT_REF((zval **) zp);
+       php_pq_params_set_param(arg->params, arg->index++, zp);
        return ZEND_HASH_APPLY_KEEP;
 }
 
@@ -337,9 +359,9 @@ unsigned php_pq_params_set_params(php_pq_params_t *p, HashTable *params)
        }
        zend_hash_clean(&p->param.dtor);
        if (p->param.count) {
-               unsigned index = 0;
+               struct apply_to_params_arg arg = {p, 0};
                p->param.strings = ecalloc(p->param.count, sizeof(*p->param.strings));
-               zend_hash_apply_with_arguments(params TSRMLS_CC, apply_to_params, 2, p, &index);
+               zend_hash_apply_with_argument(params, apply_to_params, &arg TSRMLS_CC);
        }
        return p->param.count;
 }
index 4b71038a63f10167c2266b5d2fb966f834c75707..af0eb15ea8c9707e69e09b64abaf913835205fa2 100644 (file)
@@ -164,12 +164,12 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_bind, 0, 0, 2)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(pqstm, bind) {
        long param_no;
-       zval *param_ref;
+       zval **param_ref;
        zend_error_handling zeh;
        STATUS rv;
 
        zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
-       rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &param_no, &param_ref);
+       rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lZ", &param_no, &param_ref);
        zend_restore_error_handling(&zeh TSRMLS_CC);
 
        if (SUCCESS == rv) {
@@ -178,8 +178,9 @@ static PHP_METHOD(pqstm, bind) {
                if (!obj->intern) {
                        throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
                } else {
-                       Z_ADDREF_P(param_ref);
-                       zend_hash_index_update(&obj->intern->bound, param_no, (void *) &param_ref, sizeof(zval *), NULL);
+                       SEPARATE_ZVAL_TO_MAKE_IS_REF(param_ref);
+                       Z_ADDREF_PP(param_ref);
+                       zend_hash_index_update(&obj->intern->bound, param_no, (void *) param_ref, sizeof(zval *), NULL);
                        zend_hash_sort(&obj->intern->bound, zend_qsort, compare_index, 0 TSRMLS_CC);
                }
        }