From 10f0e0a5faffafb2e2e64739541522668b523021 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Thu, 8 Feb 2007 14:33:16 +0000 Subject: [PATCH] - Fix potential issue with 'f'-parameter parsing - Complete zend_fcall_info_*() API --- Zend/zend_API.c | 57 ++++++++++++++++++++++++++++++++++++++----------- Zend/zend_API.h | 22 +++++++++++++++++++ 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 9aade4b437..0d0825edde 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -866,7 +866,6 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl int max_num_args = 0; int post_varargs = 0; zval **arg; - void **p; int arg_count; int quiet = flags & ZEND_PARSE_PARAMS_QUIET; zend_bool have_varargs = 0; @@ -887,7 +886,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl case 'o': case 'O': case 'z': case 'Z': case 't': case 'u': - case 'C': case 'h': + case 'C': case 'h': case 'U': case 'S': case 'f': case 'x': max_num_args++; @@ -958,8 +957,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl return FAILURE; } - p = EG(argument_stack).top_element-2; - arg_count = (ulong) *p; + arg_count = (ulong) *(EG(argument_stack).top_element-2); if (num_args > arg_count) { zend_error(E_WARNING, "%v(): could not obtain parameters for parsing", @@ -972,7 +970,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl for (spec_walk = type_spec, i = 0; *spec_walk && i < num_args; spec_walk++) { switch (*spec_walk) { case 'T': - arg = (zval **) p - (arg_count-i); + arg = (zval **) (EG(argument_stack).top_element - 2 - (arg_count-i)); if (Z_TYPE_PP(arg) == IS_UNICODE && (T_arg_type == -1 || T_arg_type == IS_STRING)) { /* we can upgrade from strings to Unicode */ T_arg_type = IS_UNICODE; @@ -1019,13 +1017,14 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl if (num_varargs > 0) { int iv = 0; + zval **p = (zval **) (EG(argument_stack).top_element - 2 - (arg_count - i)); + *n_varargs = num_varargs; /* allocate space for array and store args */ *varargs = safe_emalloc(num_varargs, sizeof(zval **), 0); while (num_varargs-- > 0) { - (*varargs)[iv++] = (zval **) p - (arg_count-i); - i++; + (*varargs)[iv++] = p++; } /* adjust how many args we have left and restart loop */ @@ -1037,7 +1036,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl } } - arg = (zval **) p - (arg_count-i); + arg = (zval **) (EG(argument_stack).top_element - 2 - (arg_count-i)); if (zend_parse_arg(i+1, arg, va, &type_spec, quiet, T_arg_type TSRMLS_CC) == FAILURE) { /* clean up varargs array if it was used */ @@ -2939,11 +2938,33 @@ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) return SUCCESS; } -ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) +ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) +{ + int i; + + if (argc < 0) { + return FAILURE; + } + + zend_fcall_info_args_clear(fci, !argc); + + if (argc) { + fci->param_count = argc; + fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); + + for (i = 0; i < argc; ++i) { + ZVAL_ADDREF(*(argv[i])); + fci->params[i] = argv[i]; + } + } + + return SUCCESS; +} + +ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) { int i; zval **arg; - va_list argv; if (argc < 0) { return FAILURE; @@ -2955,18 +2976,28 @@ ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) fci->param_count = argc; fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); - va_start(argv, argc); for (i = 0; i < argc; ++i) { - arg = va_arg(argv, zval **); + arg = va_arg(*argv, zval **); ZVAL_ADDREF(*arg); fci->params[i] = arg; } - va_end(argv); } return SUCCESS; } +ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) +{ + int ret; + va_list argv; + + va_start(argv, argc); + ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv); + va_end(argv); + + return ret; +} + ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) { zval *retval, ***org_params = NULL; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 45f9bcaafa..88c73fc108 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1527,8 +1527,18 @@ ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache; */ ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *callable_name TSRMLS_DC); +/** Clear argumens connected with zend_fcall_info *fci + * If free_mem is not zero then the params array gets free'd as well + */ ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem); + +/** Save current arguments from zend_fcall_info *fci + * params array will be set to NULL + */ ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params); + +/** Free arguments connected with zend_fcall_info *fci andset back saved ones. + */ ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params); /** Set or clear the arguments in the zend_call_info struct taking care of @@ -1536,6 +1546,18 @@ ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count */ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC); +/** Set arguments in the zend_fcall_info struct taking care of refcount. + * If argc is 0 the arguments which are set will be cleared, else pass + * a variable amount of zval** arguments. + */ +ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv); + +/** Set arguments in the zend_fcall_info struct taking care of refcount. + * If argc is 0 the arguments which are set will be cleared, else pass + * a variable amount of zval** arguments. + */ +ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv); + /** Set arguments in the zend_fcall_info struct taking care of refcount. * If argc is 0 the arguments which are set will be cleared, else pass * a variable amount of zval** arguments. -- 2.40.0