From 26f8fc833b9668a8b8e14ecd7d94930146019adb Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 16 Nov 2017 12:29:27 +0100 Subject: [PATCH] Enable and fix printf() format warnings Add _unchecked() variants of zend_spprintf and zend_strpprintf for cases where we specifically want to disable these checks, such as use of %H. --- Zend/zend.c | 24 ++++++++++++++++++++++++ Zend/zend.h | 5 +++++ Zend/zend_execute.c | 2 +- Zend/zend_operators.c | 2 +- Zend/zend_portability.h | 8 ++------ ext/intl/calendar/calendar_methods.cpp | 2 +- ext/mysqlnd/mysqlnd.h | 2 +- ext/mysqlnd/mysqlnd_connection.c | 2 +- ext/opcache/ZendAccelerator.c | 2 +- ext/openssl/xp_ssl.c | 6 +++--- ext/pcre/php_pcre.c | 2 +- ext/pdo/pdo_stmt.c | 16 ++++++++++------ ext/pgsql/pgsql.c | 2 +- ext/phar/dirstream.c | 2 +- ext/phar/phar_object.c | 4 ++-- ext/standard/exec.c | 8 ++++---- ext/standard/ftp_fopen_wrapper.c | 8 ++++---- ext/zip/php_zip.c | 2 +- main/streams/userspace.c | 2 +- sapi/phpdbg/phpdbg_out.h | 17 ++++++++++++----- 20 files changed, 77 insertions(+), 41 deletions(-) diff --git a/Zend/zend.c b/Zend/zend.c index 70def493cd..d2734d9803 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -202,6 +202,18 @@ ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format } /* }}} */ +ZEND_API size_t zend_spprintf_unchecked(char **message, size_t max_len, const char *format, ...) /* {{{ */ +{ + va_list arg; + size_t len; + + va_start(arg, format); + len = zend_vspprintf(message, max_len, format, arg); + va_end(arg); + return len; +} +/* }}} */ + ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */ { smart_str buf = {0}; @@ -233,6 +245,18 @@ ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) / } /* }}} */ +ZEND_API zend_string *zend_strpprintf_unchecked(size_t max_len, const char *format, ...) /* {{{ */ +{ + va_list arg; + zend_string *str; + + va_start(arg, format); + str = zend_vstrpprintf(max_len, format, arg); + va_end(arg); + return str; +} +/* }}} */ + static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent); static void print_hash(smart_str *buf, HashTable *ht, int indent, zend_bool is_object) /* {{{ */ diff --git a/Zend/zend.h b/Zend/zend.h index 3cd5036ddd..cf6bd37d5d 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -232,6 +232,11 @@ ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap); ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); +/* Same as zend_spprintf and zend_strpprintf, without checking of format validity. + * For use with custom printf specifiers such as %H. */ +ZEND_API size_t zend_spprintf_unchecked(char **message, size_t max_len, const char *format, ...); +ZEND_API zend_string *zend_strpprintf_unchecked(size_t max_len, const char *format, ...); + ZEND_API char *get_zend_version(void); ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy); ZEND_API size_t zend_print_zval(zval *expr, int indent); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 959c36a5b3..b44922f395 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1220,7 +1220,7 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(EXECUTE_DATA_D) EMPTY_SWITCH_DEFAULT_CASE(); } ZEND_ASSERT(msg != NULL); - zend_throw_error(NULL, msg); + zend_throw_error(NULL, "%s", msg); } static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value, zval *result EXECUTE_DATA_DC) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index f3d78c19bc..540f97943e 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -508,7 +508,7 @@ ZEND_API void ZEND_FASTCALL _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* { zend_string *str; double dval = Z_DVAL_P(op); - str = zend_strpprintf(0, "%.*H", (int) EG(precision), dval); + str = zend_strpprintf_unchecked(0, "%.*H", (int) EG(precision), dval); ZVAL_NEW_STR(op, str); } else { _convert_to_string(op ZEND_FILE_LINE_CC); diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index ec140b3f54..0b5e8fa0a7 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -197,17 +197,13 @@ char *alloca(); # define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y) #endif -/* Format string checks are disabled by default, because we use custom format modifiers (like %p), - * which cause a large amount of false positives. You can enable format checks by adding - * -DZEND_CHECK_FORMAT_STRINGS to CFLAGS. */ - -#if defined(ZEND_CHECK_FORMAT_STRINGS) && (ZEND_GCC_VERSION >= 2007 || __has_attribute(format)) +#if ZEND_GCC_VERSION >= 2007 || __has_attribute(format) # define ZEND_ATTRIBUTE_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first))) #else # define ZEND_ATTRIBUTE_FORMAT(type, idx, first) #endif -#if defined(ZEND_CHECK_FORMAT_STRINGS) && ((ZEND_GCC_VERSION >= 3001 && !defined(__INTEL_COMPILER)) || __has_attribute(format)) +#if (ZEND_GCC_VERSION >= 3001 && !defined(__INTEL_COMPILER)) || __has_attribute(format) # define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first))) #else # define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first) diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp index 590917d272..ce23a00a4e 100644 --- a/ext/intl/calendar/calendar_methods.cpp +++ b/ext/intl/calendar/calendar_methods.cpp @@ -1236,7 +1236,7 @@ U_CFUNC PHP_FUNCTION(intlcal_to_date_time) ZVAL_UNDEF(&retval); ts = (int64_t)date; - ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%I64d", ts); + ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%" PRIi64, ts); ZVAL_STRINGL(&ts_zval, ts_str, ts_str_len); /* Now get the time zone */ diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h index b396954eeb..1eb69558a5 100644 --- a/ext/mysqlnd/mysqlnd.h +++ b/ext/mysqlnd/mysqlnd.h @@ -162,7 +162,7 @@ PHPAPI enum_func_status mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQL /* mysqlnd metadata */ PHPAPI const char * mysqlnd_get_client_info(); -PHPAPI unsigned int mysqlnd_get_client_version(); +PHPAPI unsigned long mysqlnd_get_client_version(); #define mysqlnd_ssl_set(conn, key, cert, ca, capath, cipher) ((conn)->data)->m->ssl_set((conn)->data, (key), (cert), (ca), (capath), (cipher)) diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 75a7e02926..51450c09a2 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -1372,7 +1372,7 @@ PHPAPI const char * mysqlnd_get_client_info() /* {{{ mysqlnd_get_client_version */ -PHPAPI unsigned int mysqlnd_get_client_version() +PHPAPI unsigned long mysqlnd_get_client_version() { return MYSQLND_VERSION_ID; } diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index e6a31fba45..559322b088 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2277,7 +2277,7 @@ static void accel_activate(void) if (ZCG(counted)) { #ifdef ZTS - zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for thread id %d", tsrm_thread_id()); + zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for thread id %lu", (unsigned long) tsrm_thread_id()); #else zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for pid %d", getpid()); #endif diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index c7fe1730e9..ed14a46888 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -1399,15 +1399,15 @@ static int php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstre local_cert = zend_hash_str_find(Z_ARRVAL_P(current), "local_cert", sizeof("local_cert")-1); if (local_cert == NULL) { php_error_docref(NULL, E_WARNING, - "local_cert not present in the array", - Z_STRVAL_P(local_cert) + "local_cert not present in the array" ); return FAILURE; } convert_to_string_ex(local_cert); if (!VCWD_REALPATH(Z_STRVAL_P(local_cert), resolved_cert_path_buff)) { php_error_docref(NULL, E_WARNING, - "failed setting local cert chain file `%s'; file not found" + "failed setting local cert chain file `%s'; file not found", + Z_STRVAL_P(local_cert) ); return FAILURE; } diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index f53f39352a..fb1737897e 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -713,7 +713,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex) } #endif pcre2_get_error_message(errnumber, error, sizeof(error)); - php_error_docref(NULL,E_WARNING, "Compilation failed: %s at offset %d", error, erroffset); + php_error_docref(NULL,E_WARNING, "Compilation failed: %s at offset %zu", error, erroffset); efree(pattern); if (tables) { pefree((void*)tables, 1); diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index fcb5ae664a..c1c1b01ba5 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -305,7 +305,7 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && !Z_ISNULL_P(parameter)) { if (Z_TYPE_P(parameter) == IS_DOUBLE) { char *p; - int len = spprintf(&p, 0, "%.*H", (int) EG(precision), Z_DVAL_P(parameter)); + int len = zend_spprintf_unchecked(&p, 0, "%.*H", (int) EG(precision), Z_DVAL_P(parameter)); ZVAL_STRINGL(parameter, p, len); efree(p); } else { @@ -2132,11 +2132,15 @@ static PHP_METHOD(PDOStatement, debugDumpParams) php_stream_printf(out, "Key: Position #" ZEND_ULONG_FMT ":\n", num); } - php_stream_printf(out, "paramno=%pd\nname=[%zd] \"%.*s\"\nis_param=%d\nparam_type=%d\n", - param->paramno, param->name ? ZSTR_LEN(param->name) : 0, param->name ? (int) ZSTR_LEN(param->name) : 0, - param->name ? ZSTR_VAL(param->name) : "", - param->is_param, - param->param_type); + php_stream_printf(out, + "paramno=" ZEND_LONG_FMT "\n" + "name=[%zd] \"%.*s\"\n" + "is_param=%d\n" + "param_type=%d\n", + param->paramno, param->name ? ZSTR_LEN(param->name) : 0, param->name ? (int) ZSTR_LEN(param->name) : 0, + param->name ? ZSTR_VAL(param->name) : "", + param->is_param, + param->param_type); } ZEND_HASH_FOREACH_END(); } diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 69949d3f9c..5ff7ed471d 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -3577,7 +3577,7 @@ PHP_FUNCTION(pg_lo_write) if (argc > 2) { if (z_len > (zend_long)str_len) { - php_error_docref(NULL, E_WARNING, "Cannot write more than buffer size %d. Tried to write " ZEND_LONG_FMT, str_len, z_len); + php_error_docref(NULL, E_WARNING, "Cannot write more than buffer size %zu. Tried to write " ZEND_LONG_FMT, str_len, z_len); RETURN_FALSE; } if (z_len < 0) { diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index ce37a448f5..25374e9fa7 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -455,7 +455,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo host_len = ZSTR_LEN(resource->host); if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), host_len, NULL, 0, &error)) { - php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", resource->path+1, ZSTR_VAL(resource->host), error); + php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path) + 1, ZSTR_VAL(resource->host), error); efree(error); php_url_free(resource); return 0; diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 46423246dd..7103a05e91 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1481,7 +1481,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ if (ZEND_SIZE_T_INT_OVFL(Z_STRLEN(key))) { zval_dtor(&key); - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned an invalid key (too long)", ZSTR_VAL(ce->name)); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (too long)", ZSTR_VAL(ce->name)); return ZEND_HASH_APPLY_STOP; } @@ -1615,7 +1615,7 @@ phar_spl_fileinfo: if (ZEND_SIZE_T_INT_OVFL(Z_STRLEN(key))) { zval_dtor(&key); - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned an invalid key (too long)", ZSTR_VAL(ce->name)); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (too long)", ZSTR_VAL(ce->name)); return ZEND_HASH_APPLY_STOP; } diff --git a/ext/standard/exec.c b/ext/standard/exec.c index 1e70021674..21beaec600 100644 --- a/ext/standard/exec.c +++ b/ext/standard/exec.c @@ -295,7 +295,7 @@ PHPAPI zend_string *php_escape_shell_cmd(char *str) /* max command line length - two single quotes - \0 byte length */ if (l > cmd_max_len - 2 - 1) { - php_error_docref(NULL, E_ERROR, "Command exceeds the allowed length of %d bytes", cmd_max_len); + php_error_docref(NULL, E_ERROR, "Command exceeds the allowed length of %zu bytes", cmd_max_len); return ZSTR_EMPTY_ALLOC(); } @@ -371,7 +371,7 @@ PHPAPI zend_string *php_escape_shell_cmd(char *str) ZSTR_VAL(cmd)[y] = '\0'; if (y > cmd_max_len + 1) { - php_error_docref(NULL, E_ERROR, "Escaped command exceeds the allowed length of %d bytes", cmd_max_len); + php_error_docref(NULL, E_ERROR, "Escaped command exceeds the allowed length of %zd bytes", cmd_max_len); zend_string_release(cmd); return ZSTR_EMPTY_ALLOC(); } @@ -399,7 +399,7 @@ PHPAPI zend_string *php_escape_shell_arg(char *str) /* max command line length - two single quotes - \0 byte length */ if (l > cmd_max_len - 2 - 1) { - php_error_docref(NULL, E_ERROR, "Argument exceeds the allowed length of %d bytes", cmd_max_len); + php_error_docref(NULL, E_ERROR, "Argument exceeds the allowed length of %zd bytes", cmd_max_len); return ZSTR_EMPTY_ALLOC(); } @@ -458,7 +458,7 @@ PHPAPI zend_string *php_escape_shell_arg(char *str) ZSTR_VAL(cmd)[y] = '\0'; if (y > cmd_max_len + 1) { - php_error_docref(NULL, E_ERROR, "Escaped argument exceeds the allowed length of %d bytes", cmd_max_len); + php_error_docref(NULL, E_ERROR, "Escaped argument exceeds the allowed length of %zu bytes", cmd_max_len); zend_string_release(cmd); return ZSTR_EMPTY_ALLOC(); } diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index b548dddc5f..dfa011c891 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -264,7 +264,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char if (resource->pass != NULL) { ZSTR_LEN(resource->pass) = php_raw_url_decode(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass)); - PHP_FTP_CNTRL_CHK(resource->pass, ZSTR_LEN(resource->pass), "Invalid password %s") + PHP_FTP_CNTRL_CHK(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass), "Invalid password %s") php_stream_printf(stream, "PASS %s\r\n", ZSTR_VAL(resource->pass)); } else { @@ -475,7 +475,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa goto errexit; /* find out the size of the file (verifying it exists) */ - php_stream_printf(stream, "SIZE %s\r\n", resource->path); + php_stream_printf(stream, "SIZE %s\r\n", ZSTR_VAL(resource->path)); /* read the response */ result = GET_FTP_RESULT(stream); @@ -504,7 +504,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa if (allow_overwrite) { /* Context permits overwriting file, so we just delete whatever's there in preparation */ - php_stream_printf(stream, "DELE %s\r\n", resource->path); + php_stream_printf(stream, "DELE %s\r\n", ZSTR_VAL(resource->path)); result = GET_FTP_RESULT(stream); if (result >= 300 || result <= 199) { goto errexit; @@ -1144,7 +1144,7 @@ static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const char *url, in goto rmdir_errexit; } - php_stream_printf(stream, "RMD %s\r\n", resource->path); + php_stream_printf(stream, "RMD %s\r\n", ZSTR_VAL(resource->path)); result = GET_FTP_RESULT(stream); if (result < 200 || result > 299) { diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index fdc3e90345..209663e3a5 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -678,7 +678,7 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val } if ((path_len + namelist_len + 1) >= MAXPATHLEN) { - php_error_docref(NULL, E_WARNING, "add_path string too long (max: %i, %i given)", + php_error_docref(NULL, E_WARNING, "add_path string too long (max: %u, %zu given)", MAXPATHLEN - 1, (path_len + namelist_len + 1)); zend_string_release(namelist[i]); break; diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 81ce3d0e19..59dddfd42d 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -546,7 +546,7 @@ PHP_FUNCTION(stream_wrapper_unregister) if (php_unregister_url_stream_wrapper_volatile(protocol) == FAILURE) { /* We failed */ - php_error_docref(NULL, E_WARNING, "Unable to unregister protocol %s://", protocol); + php_error_docref(NULL, E_WARNING, "Unable to unregister protocol %s://", ZSTR_VAL(protocol)); RETURN_FALSE; } diff --git a/sapi/phpdbg/phpdbg_out.h b/sapi/phpdbg/phpdbg_out.h index fe0bbe99ba..000a81f3d8 100644 --- a/sapi/phpdbg/phpdbg_out.h +++ b/sapi/phpdbg/phpdbg_out.h @@ -34,11 +34,18 @@ enum { P_LOG }; -PHPDBG_API int phpdbg_print(int severity, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 5, 6); -PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); -PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); -PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); -PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); +/* phpdbg uses lots of custom format specifiers, so we disable format checks by default. */ +#if defined(PHPDBG_CHECK_FORMAT_STRINGS) +# define PHPDBG_ATTRIBUTE_FORMAT(type, idx, first) PHP_ATTRIBUTE_FORMAT(type, idx, first) +#else +# define PHPDBG_ATTRIBUTE_FORMAT(type, idx, first) +#endif + +PHPDBG_API int phpdbg_print(int severity, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) PHPDBG_ATTRIBUTE_FORMAT(printf, 5, 6); +PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) PHPDBG_ATTRIBUTE_FORMAT(printf, 2, 3); +PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) PHPDBG_ATTRIBUTE_FORMAT(printf, 2, 3); +PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) PHPDBG_ATTRIBUTE_FORMAT(printf, 2, 3); +PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) PHPDBG_ATTRIBUTE_FORMAT(printf, 2, 3); #define phpdbg_error(tag, xmlfmt, strfmt, ...) phpdbg_print(P_ERROR , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) #define phpdbg_notice(tag, xmlfmt, strfmt, ...) phpdbg_print(P_NOTICE , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) -- 2.40.0