From a5a4261161f5afcfff6cf22a5b255caa7c413779 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Tue, 3 Oct 2017 10:40:07 +0200 Subject: [PATCH 1/3] Throw exception if WinAPI call fails That should never happen so throw an exception just in case --- include/boost/nowide/args.hpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/boost/nowide/args.hpp b/include/boost/nowide/args.hpp index 514c0a7..134e04b 100644 --- a/include/boost/nowide/args.hpp +++ b/include/boost/nowide/args.hpp @@ -9,10 +9,11 @@ #define BOOST_NOWIDE_ARGS_HPP_INCLUDED #include +#ifdef BOOST_WINDOWS #include #include -#ifdef BOOST_WINDOWS #include +#include #endif namespace boost { @@ -84,14 +85,10 @@ namespace nowide { private: void fix_args(int &argc,char **&argv) { - int wargc; - wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc); - if(!wargv) { - argc = 0; - static char *dummy = 0; - argv = &dummy; - return; - } + int wargc; + wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc); + if(!wargv) + throw std::runtime_error("Could not get command line!"); try{ args_.resize(wargc+1,0); arg_values_.resize(wargc); @@ -112,7 +109,7 @@ namespace nowide { en = &dummy; wchar_t *wstrings = GetEnvironmentStringsW(); if(!wstrings) - return; + throw std::runtime_error("Could not get environment strings!"); try { wchar_t *wstrings_end = 0; int count = 0; From 72565401eaaa38c18ace5bc91d8a113b64b8afca Mon Sep 17 00:00:00 2001 From: Flamefire Date: Fri, 13 Dec 2019 19:47:49 +0100 Subject: [PATCH 2/3] Remove try-catch and document the thrown exception The try-catch is not required because no exception can be thrown anymore. Invalid UTF-16 (formerly indicated by an exception) is now replaced by the replacement character. --- include/boost/nowide/args.hpp | 72 +++++++++++++++-------------------- 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/include/boost/nowide/args.hpp b/include/boost/nowide/args.hpp index 134e04b..95bfd3d 100644 --- a/include/boost/nowide/args.hpp +++ b/include/boost/nowide/args.hpp @@ -33,18 +33,21 @@ namespace nowide { /// Microsoft Windows. /// /// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW() - /// in order to obtain the information. It does not relates to actual values of argc,argv and env + /// in order to obtain the information. It does not relate to actual values of argc,argv and env /// under Windows. /// /// It restores the original values in its destructor /// + /// If any of the system calls fails, an exception of type std::runtime_error will be thrown + /// and argc, argv, env remain unchanged. + /// /// \note the class owns the memory of the newly allocated strings /// class args { public: /// - /// Fix command line agruments + /// Fix command line arguments /// args(int &argc,char **&argv) : old_argc_(argc), @@ -57,18 +60,18 @@ namespace nowide { fix_args(argc,argv); } /// - /// Fix command line agruments and environment + /// Fix command line arguments and environment /// - args(int &argc,char **&argv,char **&en) : + args(int &argc,char **&argv,char **&env) : old_argc_(argc), old_argv_(argv), - old_env_(en), + old_env_(env), old_argc_ptr_(&argc), old_argv_ptr_(&argv), - old_env_ptr_(&en) + old_env_ptr_(&env) { fix_args(argc,argv); - fix_env(en); + fix_env(env); } /// /// Restore original argc,argv,env values, if changed @@ -89,49 +92,34 @@ namespace nowide { wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc); if(!wargv) throw std::runtime_error("Could not get command line!"); - try{ - args_.resize(wargc+1,0); - arg_values_.resize(wargc); - for(int i=0;i args_; From ea99c1d1ca40d64adb835fed4ff4165c81101ee0 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Fri, 13 Dec 2019 20:30:55 +0100 Subject: [PATCH 3/3] Avoid memory leak in fix_args/fix_env Throwing bad_alloc from vector::resize could leak memory --- include/boost/nowide/args.hpp | 39 ++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/include/boost/nowide/args.hpp b/include/boost/nowide/args.hpp index 95bfd3d..feb436d 100644 --- a/include/boost/nowide/args.hpp +++ b/include/boost/nowide/args.hpp @@ -86,26 +86,46 @@ namespace nowide { *old_env_ptr_ = old_env_; } private: + class wargv_ptr + { + wchar_t **p; + int argc; + wargv_ptr(const wargv_ptr &); // Non-copyable + public: + explicit wargv_ptr(const wchar_t *cmd_line) : p(CommandLineToArgvW(GetCommandLineW(), &argc)) {} + ~wargv_ptr() { if(p) LocalFree(p); } + int size() const { return argc; } + operator bool() const { return p != NULL; } + const wchar_t* operator[](size_t i) const { return p[i]; } + }; + class wenv_ptr + { + wchar_t *p; + wenv_ptr(const wenv_ptr &); // Non-copyable + public: + wenv_ptr() : p(GetEnvironmentStringsW()) {} + ~wenv_ptr() { if(p) FreeEnvironmentStringsW(p); } + operator const wchar_t*() const { return p; } + }; + void fix_args(int &argc,char **&argv) { - int wargc; - wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc); + const wargv_ptr wargv(GetCommandLineW()); if(!wargv) throw std::runtime_error("Could not get command line!"); - args_.resize(wargc+1,0); - arg_values_.resize(wargc); - for(int i=0;i args_;