Fix crash using "--command" on Windows
Use after free error accessing command line arguments on windows. Resolve by duplicating the arguments when a "--command" is passed in.
This commit is contained in:
@@ -567,8 +567,8 @@ int main(int argc,
|
||||
if (G.background) {
|
||||
int exit_code;
|
||||
if (app_state.main_arg_deferred != nullptr) {
|
||||
exit_code = main_arg_handle_deferred();
|
||||
MEM_freeN(app_state.main_arg_deferred);
|
||||
exit_code = main_arg_deferred_handle();
|
||||
main_arg_deferred_free();
|
||||
}
|
||||
else {
|
||||
exit_code = G.is_break ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
|
||||
@@ -429,6 +429,28 @@ fail:
|
||||
* (Python in particular) * to be initialized.
|
||||
* \{ */
|
||||
|
||||
/* When the deferred argument is handled on Windows the `argv` will have been freed,
|
||||
* see `USE_WIN32_UNICODE_ARGS` in `creator.cc`. */
|
||||
|
||||
# ifdef WIN32
|
||||
static char **argv_duplicate(const char **argv, int argc)
|
||||
{
|
||||
char **argv_copy = static_cast<char **>(MEM_mallocN(sizeof(*argv_copy) * argc, __func__));
|
||||
for (int i = 0; i < argc; i++) {
|
||||
argv_copy[i] = BLI_strdup(argv[i]);
|
||||
}
|
||||
return argv_copy;
|
||||
}
|
||||
|
||||
static void argv_free(char **argv, int argc)
|
||||
{
|
||||
for (int i = 0; i < argc; i++) {
|
||||
MEM_freeN(argv[i]);
|
||||
}
|
||||
MEM_freeN(argv);
|
||||
}
|
||||
# endif /* !WIN32 */
|
||||
|
||||
struct BA_ArgCallback_Deferred {
|
||||
BA_ArgCallback func;
|
||||
int argc;
|
||||
@@ -453,9 +475,22 @@ static void main_arg_deferred_setup(BA_ArgCallback func, int argc, const char **
|
||||
d->argv = argv;
|
||||
d->data = data;
|
||||
d->exit_code = 0;
|
||||
# ifdef WIN32
|
||||
d->argv = const_cast<const char **>(argv_duplicate(d->argv, d->argc));
|
||||
# endif
|
||||
app_state.main_arg_deferred = d;
|
||||
}
|
||||
|
||||
void main_arg_deferred_free()
|
||||
{
|
||||
BA_ArgCallback_Deferred *d = app_state.main_arg_deferred;
|
||||
app_state.main_arg_deferred = nullptr;
|
||||
# ifdef WIN32
|
||||
argv_free(const_cast<char **>(d->argv), d->argc);
|
||||
# endif
|
||||
MEM_freeN(d);
|
||||
}
|
||||
|
||||
static void main_arg_deferred_exit_code_set(int exit_code)
|
||||
{
|
||||
BA_ArgCallback_Deferred *d = app_state.main_arg_deferred;
|
||||
@@ -463,7 +498,7 @@ static void main_arg_deferred_exit_code_set(int exit_code)
|
||||
d->exit_code = exit_code;
|
||||
}
|
||||
|
||||
int main_arg_handle_deferred()
|
||||
int main_arg_deferred_handle()
|
||||
{
|
||||
BA_ArgCallback_Deferred *d = app_state.main_arg_deferred;
|
||||
d->func(d->argc, d->argv, d->data);
|
||||
|
||||
@@ -38,7 +38,8 @@ int main_args_handle_load_file(int argc, const char **argv, void *data);
|
||||
* Handle an argument which requested deferred evaluation.
|
||||
* Needed when arguments which evaluate early need Python to be initialized for example.
|
||||
*/
|
||||
int main_arg_handle_deferred();
|
||||
int main_arg_deferred_handle();
|
||||
void main_arg_deferred_free();
|
||||
|
||||
/* `creator_signals.cc` */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user