From 321c0cc3493998f731f0666127c093eff4e119eb Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 17 Sep 2018 09:48:33 +0200 Subject: [PATCH] Fix localized error messages and memory leaks The FormatMessage API needs to LocalFree the delivered error messages. In cases where messages are delivered in non ASCII compatible encoding, the messages might be unreadable. This aligns the error message encoding with the encoding settings in PHP, the focus is UTF-8 as default. Initialize error buffer Avoid code duplication --- Zend/zend_alloc.c | 15 ++++-------- ext/com_dotnet/com_com.c | 16 ++++++------- ext/com_dotnet/com_dotnet.c | 13 ++++------- ext/com_dotnet/com_misc.c | 2 +- ext/com_dotnet/com_olechar.c | 4 ++-- ext/com_dotnet/com_variant.c | 6 ++--- ext/opcache/shared_alloc_win32.c | 21 ++++------------- ext/openssl/xp_ssl.c | 12 +++++++--- ext/sockets/sockets.c | 35 +++++++++------------------- ext/standard/dl.c | 2 +- ext/standard/exec.c | 4 +++- ext/standard/filestat.c | 8 +++++-- ext/standard/var_unserializer.c | 2 +- main/main.c | 22 +++++++----------- main/network.c | 40 ++++++-------------------------- main/php_ini.c | 1 + sapi/cgi/cgi_main.c | 6 +++++ sapi/phpdbg/phpdbg_prompt.c | 2 +- win32/winutil.c | 27 +++++++++++++++++---- win32/winutil.h | 2 ++ 20 files changed, 105 insertions(+), 135 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index c1250d1e786..d3b24612018 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -68,6 +68,7 @@ #ifdef ZEND_WIN32 # include # include +# include "win32/winutil.h" #endif #include @@ -394,23 +395,17 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap, void stderr_last_error(char *msg) { - LPSTR buf = NULL; DWORD err = GetLastError(); + char *buf = php_win32_error_to_msg(err); - if (!FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&buf, - 0, NULL)) { + if (!buf[0]) { fprintf(stderr, "\n%s: [0x%08lx]\n", msg, err); } else { fprintf(stderr, "\n%s: [0x%08lx] %s\n", msg, err, buf); } + + php_win32_error_msg_free(buf); } #endif diff --git a/ext/com_dotnet/com_com.c b/ext/com_dotnet/com_com.c index eb79ed76ff0..5ddf3358c54 100644 --- a/ext/com_dotnet/com_com.c +++ b/ext/com_dotnet/com_com.c @@ -231,7 +231,7 @@ PHP_FUNCTION(com_create_instance) werr = php_win32_error_to_msg(res); spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name, werr); - LocalFree(werr); + php_win32_error_msg_free(werr); php_com_throw_exception(res, msg); efree(msg); @@ -389,7 +389,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member, case DISP_E_TYPEMISMATCH: desc = php_win32_error_to_msg(hr); spprintf(&msg, 0, "Parameter %d: %s", arg_err, desc); - LocalFree(desc); + php_win32_error_msg_free(desc); break; case DISP_E_BADPARAMCOUNT: @@ -405,7 +405,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member, default: desc = php_win32_error_to_msg(hr); spprintf(&msg, 0, "Error [0x%08x] %s", hr, desc); - LocalFree(desc); + php_win32_error_msg_free(desc); break; } @@ -485,11 +485,10 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, zend_internal_function * hr = php_com_get_id_of_name(obj, f->function_name->val, f->function_name->len, &dispid); if (FAILED(hr)) { - char *winerr = NULL; char *msg = NULL; - winerr = php_win32_error_to_msg(hr); + char *winerr = php_win32_error_to_msg(hr); spprintf(&msg, 0, "Unable to lookup `%s': %s", f->function_name->val, winerr); - LocalFree(winerr); + php_win32_error_msg_free(winerr); php_com_throw_exception(hr, msg); efree(msg); return FAILURE; @@ -648,15 +647,14 @@ int php_com_do_invoke(php_com_dotnet_object *obj, char *name, size_t namelen, { DISPID dispid; HRESULT hr; - char *winerr = NULL; char *msg = NULL; hr = php_com_get_id_of_name(obj, name, namelen, &dispid); if (FAILED(hr)) { - winerr = php_win32_error_to_msg(hr); + char *winerr = php_win32_error_to_msg(hr); spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr); - LocalFree(winerr); + php_win32_error_msg_free(winerr); php_com_throw_exception(hr, msg); efree(msg); return FAILURE; diff --git a/ext/com_dotnet/com_dotnet.c b/ext/com_dotnet/com_dotnet.c index f8bdefdf215..f5224363658 100644 --- a/ext/com_dotnet/com_dotnet.c +++ b/ext/com_dotnet/com_dotnet.c @@ -205,8 +205,7 @@ PHP_FUNCTION(com_dotnet_create_instance) char buf[1024]; char *err = php_win32_error_to_msg(hr); snprintf(buf, sizeof(buf), "Failed to init .Net runtime [%s] %s", where, err); - if (err) - LocalFree(err); + php_win32_error_msg_free(err); php_com_throw_exception(hr, buf); return; } @@ -219,8 +218,7 @@ PHP_FUNCTION(com_dotnet_create_instance) char buf[1024]; char *err = php_win32_error_to_msg(hr); snprintf(buf, sizeof(buf), "Failed to re-init .Net domain [%s] %s", where, err); - if (err) - LocalFree(err); + php_win32_error_msg_free(err); php_com_throw_exception(hr, buf); ZVAL_NULL(object); return; @@ -232,8 +230,7 @@ PHP_FUNCTION(com_dotnet_create_instance) char buf[1024]; char *err = php_win32_error_to_msg(hr); snprintf(buf, sizeof(buf), "Failed to re-init .Net domain [%s] %s", where, err); - if (err) - LocalFree(err); + php_win32_error_msg_free(err); php_com_throw_exception(hr, buf); ZVAL_NULL(object); return; @@ -315,9 +312,7 @@ PHP_FUNCTION(com_dotnet_create_instance) char buf[1024]; char *err = php_win32_error_to_msg(hr); snprintf(buf, sizeof(buf), "Failed to instantiate .Net object [%s] [0x%08x] %s", where, hr, err); - if (err && err[0]) { - LocalFree(err); - } + php_win32_error_msg_free(err); php_com_throw_exception(hr, buf); return; } diff --git a/ext/com_dotnet/com_misc.c b/ext/com_dotnet/com_misc.c index 6488b3c8b44..c534117f9d8 100644 --- a/ext/com_dotnet/com_misc.c +++ b/ext/com_dotnet/com_misc.c @@ -40,7 +40,7 @@ void php_com_throw_exception(HRESULT code, char *message) zend_throw_exception(php_com_exception_class_entry, message, (zend_long)code); #endif if (free_msg) { - LocalFree(message); + php_win32_error_msg_free(message); } } diff --git a/ext/com_dotnet/com_olechar.c b/ext/com_dotnet/com_olechar.c index b9a332e4f54..c586756ad72 100644 --- a/ext/com_dotnet/com_olechar.c +++ b/ext/com_dotnet/com_olechar.c @@ -63,7 +63,7 @@ PHP_COM_DOTNET_API OLECHAR *php_com_string_to_olestring(char *string, size_t str php_error_docref(NULL, E_WARNING, "Could not convert string to unicode: `%s'", msg); - LocalFree(msg); + php_win32_error_msg_free(msg); } return olestring; @@ -94,7 +94,7 @@ PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring, size_t php_error_docref(NULL, E_WARNING, "Could not convert string from unicode: `%s'", msg); - LocalFree(msg); + php_win32_error_msg_free(msg); } if (string_len) { diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index 170f15b6e72..e2b515caad6 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -490,7 +490,7 @@ PHP_FUNCTION(com_variant_create_instance) werr = php_win32_error_to_msg(res); spprintf(&msg, 0, "Variant type conversion failed: %s", werr); - LocalFree(werr); + php_win32_error_msg_free(werr); php_com_throw_exception(res, msg); efree(msg); @@ -1078,7 +1078,7 @@ PHP_FUNCTION(variant_set_type) werr = php_win32_error_to_msg(res); spprintf(&msg, 0, "Variant type conversion failed: %s", werr); - LocalFree(werr); + php_win32_error_msg_free(werr); php_com_throw_exception(res, msg); efree(msg); @@ -1112,7 +1112,7 @@ PHP_FUNCTION(variant_cast) werr = php_win32_error_to_msg(res); spprintf(&msg, 0, "Variant type conversion failed: %s", werr); - LocalFree(werr); + php_win32_error_msg_free(werr); php_com_throw_exception(res, msg); efree(msg); diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c index 5207a598127..91797558495 100644 --- a/ext/opcache/shared_alloc_win32.c +++ b/ext/opcache/shared_alloc_win32.c @@ -23,6 +23,7 @@ #include "zend_shared_alloc.h" #include "zend_accelerator_util_funcs.h" #include "tsrm_win32.h" +#include "win32/winutil.h" #include #include #include @@ -40,25 +41,13 @@ static void *mapping_base; static void zend_win_error_message(int type, char *msg, int err) { - LPVOID lpMsgBuf; HANDLE h; char *ev_msgs[2]; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); + char *buf = php_win32_error_to_msg(err); h = RegisterEventSource(NULL, TEXT(ACCEL_EVENT_SOURCE)); ev_msgs[0] = msg; - ev_msgs[1] = lpMsgBuf; + ev_msgs[1] = buf; ReportEvent(h, // event log handle EVENTLOG_ERROR_TYPE, // event type 0, // category zero @@ -70,9 +59,9 @@ static void zend_win_error_message(int type, char *msg, int err) NULL); // pointer to data DeregisterEventSource(h); - LocalFree( lpMsgBuf ); - zend_accel_error(type, "%s", msg); + + php_win32_error_msg_free(buf); } static char *create_name_with_username(char *name) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 11bea412953..4c4bfaddd3e 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -637,7 +637,9 @@ static int php_openssl_win_cert_verify_callback(X509_STORE_CTX *x509_store_ctx, OPENSSL_free(der_buf); if (cert_ctx == NULL) { - php_error_docref(NULL, E_WARNING, "Error creating certificate context: %s", php_win_err()); + char *err = php_win_err(); + php_error_docref(NULL, E_WARNING, "Error creating certificate context: %s", err); + php_win_err_free(err); RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED); } } @@ -659,7 +661,9 @@ static int php_openssl_win_cert_verify_callback(X509_STORE_CTX *x509_store_ctx, chain_flags = CERT_CHAIN_CACHE_END_CERT | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; if (!CertGetCertificateChain(NULL, cert_ctx, NULL, NULL, &chain_params, chain_flags, NULL, &cert_chain_ctx)) { - php_error_docref(NULL, E_WARNING, "Error getting certificate chain: %s", php_win_err()); + char *err = php_win_err(); + php_error_docref(NULL, E_WARNING, "Error getting certificate chain: %s", err); + php_win_err_free(err); CertFreeCertificateContext(cert_ctx); RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED); } @@ -743,7 +747,9 @@ static int php_openssl_win_cert_verify_callback(X509_STORE_CTX *x509_store_ctx, CertFreeCertificateContext(cert_ctx); if (!verify_result) { - php_error_docref(NULL, E_WARNING, "Error verifying certificate chain policy: %s", php_win_err()); + char *err = php_win_err(); + php_error_docref(NULL, E_WARNING, "Error verifying certificate chain policy: %s", err); + php_win_err_free(err); RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED); } diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index e8e689f83af..748f2101288 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -37,6 +37,7 @@ # include # include "php_sockets.h" # include +# include #else # include # include @@ -649,12 +650,10 @@ char *sockets_strerror(int error) /* {{{ */ } #else { - LPTSTR tmp = NULL; + char *tmp = php_win32_error_to_msg(error); buf = NULL; - if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &tmp, 0, NULL) - ) { + if (tmp[0]) { if (SOCKETS_G(strerror_buf)) { efree(SOCKETS_G(strerror_buf)); } @@ -2822,22 +2821,16 @@ PHP_FUNCTION(socket_wsaprotocol_info_export) if (SOCKET_ERROR == WSADuplicateSocket(socket->bsd_socket, (DWORD)target_pid, &wi)) { DWORD err = WSAGetLastError(); - LPSTR buf = NULL; + char *buf = php_win32_error_to_msg(err); - if (!FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&buf, - 0, NULL)) { + if (!buf[0]) { php_error_docref(NULL, E_WARNING, "Unable to export WSA protocol info [0x%08lx]", err); } else { php_error_docref(NULL, E_WARNING, "Unable to export WSA protocol info [0x%08lx]: %s", err, buf); } + php_win32_error_msg_free(buf); + RETURN_FALSE; } @@ -2900,22 +2893,16 @@ PHP_FUNCTION(socket_wsaprotocol_info_import) sock = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &wi, 0, 0); if (INVALID_SOCKET == sock) { DWORD err = WSAGetLastError(); - LPSTR buf = NULL; + char *buf = php_win32_error_to_msg(err); - if (!FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&buf, - 0, NULL)) { + if (!buf[0]) { php_error_docref(NULL, E_WARNING, "Unable to import WSA protocol info [0x%08lx]", err); } else { php_error_docref(NULL, E_WARNING, "Unable to import WSA protocol info [0x%08lx]: %s", err, buf); } + php_win32_error_msg_free(buf); + RETURN_FALSE; } diff --git a/ext/standard/dl.c b/ext/standard/dl.c index 6b50f22bf47..5ac18f126ff 100644 --- a/ext/standard/dl.c +++ b/ext/standard/dl.c @@ -88,7 +88,7 @@ PHPAPI void *php_load_shlib(char *path, char **errp) if (err && (*err)) { size_t i = strlen(err); (*errp)=estrdup(err); - LocalFree(err); + php_win32_error_msg_free(err); while (i > 0 && isspace((*errp)[i-1])) { (*errp)[i-1] = '\0'; i--; } } else { (*errp) = estrdup(""); diff --git a/ext/standard/exec.c b/ext/standard/exec.c index d914a1fd726..5b885c554d8 100644 --- a/ext/standard/exec.c +++ b/ext/standard/exec.c @@ -564,7 +564,9 @@ PHP_FUNCTION(proc_nice) php_ignore_value(nice(pri)); if (errno) { #ifdef PHP_WIN32 - php_error_docref(NULL, E_WARNING, "%s", php_win_err()); + char *err = php_win_err(); + php_error_docref(NULL, E_WARNING, "%s", err); + php_win_err_free(err); #else php_error_docref(NULL, E_WARNING, "Only a super user may attempt to increase the priority of a process"); #endif diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index 3a3c024b6ae..6073922f381 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -114,7 +114,9 @@ static int php_disk_total_space(char *path, double *space) /* {{{ */ PHP_WIN32_IOUTIL_INIT_W(path) if (GetDiskFreeSpaceExW(pathw, &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes) == 0) { - php_error_docref(NULL, E_WARNING, "%s", php_win_err()); + char *err = php_win_err(); + php_error_docref(NULL, E_WARNING, "%s", err); + php_win_err_free(err); PHP_WIN32_IOUTIL_CLEANUP_W() return FAILURE; } @@ -208,7 +210,9 @@ static int php_disk_free_space(char *path, double *space) /* {{{ */ PHP_WIN32_IOUTIL_INIT_W(path) if (GetDiskFreeSpaceExW(pathw, &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes) == 0) { - php_error_docref(NULL, E_WARNING, "%s", php_win_err()); + char *err = php_win_err(); + php_error_docref(NULL, E_WARNING, "%s", err); + php_win_err_free(err); PHP_WIN32_IOUTIL_CLEANUP_W() return FAILURE; } diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 518277ca00a..3c1c18a700c 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 1.0.1 */ +/* Generated by re2c 1.0.3 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ diff --git a/main/main.c b/main/main.c index c9c05dece5c..e77ec61ca87 100644 --- a/main/main.c +++ b/main/main.c @@ -1162,24 +1162,18 @@ PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, /* }}} */ #ifdef PHP_WIN32 -#define PHP_WIN32_ERROR_MSG_BUFFER_SIZE 512 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) { - if (error == 0) { - php_error_docref2(NULL, param1, param2, E_WARNING, "%s", strerror(errno)); - } else { - char buf[PHP_WIN32_ERROR_MSG_BUFFER_SIZE + 1]; - size_t buf_len; + char *buf = php_win32_error_to_msg(error); + size_t buf_len; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, buf, PHP_WIN32_ERROR_MSG_BUFFER_SIZE, NULL); - buf_len = strlen(buf); - if (buf_len >= 2) { - buf[buf_len - 1] = '\0'; - buf[buf_len - 2] = '\0'; - } - php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", (char *)buf, error); + buf_len = strlen(buf); + if (buf_len >= 2) { + buf[buf_len - 1] = '\0'; + buf[buf_len - 2] = '\0'; } + php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", buf, error); + php_win32_error_msg_free(buf); } -#undef PHP_WIN32_ERROR_MSG_BUFFER_SIZE #endif /* {{{ php_html_puts */ diff --git a/main/network.c b/main/network.c index 7eccb360472..94f4a838718 100644 --- a/main/network.c +++ b/main/network.c @@ -28,6 +28,7 @@ #ifdef PHP_WIN32 # include # include "win32/inet.h" +# include "win32/winutil.h" # define O_RDONLY _O_RDONLY # include "win32/param.h" #else @@ -1020,20 +1021,8 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) } return buf; #else - char *sysbuf; - int free_it = 1; - - if (!FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&sysbuf, - 0, - NULL)) { - free_it = 0; + char *sysbuf = php_win32_error_to_msg(err); + if (!sysbuf[0]) { sysbuf = "Unknown Error"; } @@ -1044,9 +1033,7 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) buf[bufsize?(bufsize-1):0] = 0; } - if (free_it) { - LocalFree(sysbuf); - } + php_win32_error_msg_free(sysbuf); return buf; #endif @@ -1063,28 +1050,15 @@ PHPAPI zend_string *php_socket_error_str(long err) return zend_string_init(errstr, strlen(errstr), 0); #else zend_string *ret; - char *sysbuf; - int free_it = 1; - if (!FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&sysbuf, - 0, - NULL)) { - free_it = 0; + char *sysbuf = php_win32_error_to_msg(err); + if (!sysbuf[0]) { sysbuf = "Unknown Error"; } ret = zend_string_init(sysbuf, strlen(sysbuf), 0); - if (free_it) { - LocalFree(sysbuf); - } + php_win32_error_msg_free(sysbuf); return ret; #endif diff --git a/main/php_ini.c b/main/php_ini.c index 24c3cdd5c57..c01eef98517 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -29,6 +29,7 @@ #include "php_scandir.h" #ifdef PHP_WIN32 #include "win32/php_registry.h" +#include "win32/winutil.h" #endif #if HAVE_SCANDIR && HAVE_ALPHASORT && HAVE_DIRENT_H diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 4041f937899..a4be18aaed1 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -2149,6 +2149,7 @@ consult the installation file that came with this distribution, or visit \n\ char *err_text = php_win32_error_to_msg(err); fprintf(stderr, "unable to get current command line: [0x%08lx]: %s\n", err, err_text); + php_win32_error_msg_free(err_text); goto parent_out; } @@ -2167,6 +2168,8 @@ consult the installation file that came with this distribution, or visit \n\ fprintf(stderr, "unable to create job object: [0x%08lx]: %s\n", err, err_text); + php_win32_error_msg_free(err_text); + goto parent_out; } @@ -2176,6 +2179,7 @@ consult the installation file that came with this distribution, or visit \n\ char *err_text = php_win32_error_to_msg(err); fprintf(stderr, "unable to configure job object: [0x%08lx]: %s\n", err, err_text); + php_win32_error_msg_free(err_text); } while (parent) { @@ -2216,6 +2220,7 @@ consult the installation file that came with this distribution, or visit \n\ char *err_text = php_win32_error_to_msg(err); fprintf(stderr, "unable to assign child process to job object: [0x%08lx]: %s\n", err, err_text); + php_win32_error_msg_free(err_text); } CloseHandle(pi.hThread); } else { @@ -2225,6 +2230,7 @@ consult the installation file that came with this distribution, or visit \n\ kid_cgi_ps[i] = NULL; fprintf(stderr, "unable to spawn: [0x%08lx]: %s\n", err, err_text); + php_win32_error_msg_free(err_text); } } diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 8815b90be21..f4b5a11fefa 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -1311,7 +1311,7 @@ PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, char **name) char *err = GET_DL_ERROR(); if (err && err[0]) { phpdbg_error("dl", "type=\"unknown\"", "%s", err); - LocalFree(err); + php_win32_error_msg_free(err); } else { phpdbg_error("dl", "type=\"unknown\"", "Unknown reason"); } diff --git a/win32/winutil.c b/win32/winutil.c index d719bb6ee57..e44d876d495 100644 --- a/win32/winutil.c +++ b/win32/winutil.c @@ -19,19 +19,36 @@ #include "php.h" #include "winutil.h" +#include "codepage.h" #include #include PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error) {/*{{{*/ - char *buf = NULL; + wchar_t *bufw = NULL; + char *buf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL + DWORD ret = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&bufw, 0, NULL ); - return (buf ? (char *) buf : ""); + if (!ret || !bufw) { + return ""; + } + + buf = php_win32_cp_conv_w_to_any(bufw, ret, PHP_WIN32_CP_IGNORE_LEN_P); + + LocalFree(bufw); + + return (buf ? buf : ""); +}/*}}}*/ + +PHP_WINUTIL_API void php_win32_error_msg_free(char *msg) +{/*{{{*/ + if (msg && msg[0]) { + free(msg); + } }/*}}}*/ int php_win32_check_trailing_space(const char * path, const size_t path_len) diff --git a/win32/winutil.h b/win32/winutil.h index c08ab5e27ee..63837c95a03 100644 --- a/win32/winutil.h +++ b/win32/winutil.h @@ -26,8 +26,10 @@ #endif PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error); +PHP_WINUTIL_API void php_win32_error_msg_free(char *msg); #define php_win_err() php_win32_error_to_msg(GetLastError()) +#define php_win_err_free(err) php_win32_error_msg_free(err) int php_win32_check_trailing_space(const char * path, const size_t path_len); PHP_WINUTIL_API int php_win32_get_random_bytes(unsigned char *buf, size_t size); #ifdef PHP_EXPORTS