Skip to content

Commit 82fbf26

Browse files
peffgitster
authored andcommitted
run_external_diff: use an argv_array for the command line
We currently generate the command-line for the external command using a fixed-length array of size 10. But if there is a rename, we actually need 11 elements (10 items, plus a NULL), and end up writing a random NULL onto the stack. Rather than bump the limit, let's just use an argv_array, which makes this sort of error impossible. Noticed-by: Max L <[email protected]> Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0bc85ab commit 82fbf26

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

diff.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "submodule.h"
1717
#include "ll-merge.h"
1818
#include "string-list.h"
19+
#include "argv-array.h"
1920

2021
#ifdef NO_FAST_WORKING_DIRECTORY
2122
#define FAST_WORKING_DIRECTORY 0
@@ -2906,9 +2907,8 @@ static void run_external_diff(const char *pgm,
29062907
int complete_rewrite,
29072908
struct diff_options *o)
29082909
{
2909-
const char *spawn_arg[10];
2910+
struct argv_array argv = ARGV_ARRAY_INIT;
29102911
int retval;
2911-
const char **arg = &spawn_arg[0];
29122912
struct diff_queue_struct *q = &diff_queued_diff;
29132913
const char *env[3] = { NULL };
29142914
char env_counter[50];
@@ -2919,23 +2919,22 @@ static void run_external_diff(const char *pgm,
29192919
const char *othername = (other ? other : name);
29202920
temp_one = prepare_temp_file(name, one);
29212921
temp_two = prepare_temp_file(othername, two);
2922-
*arg++ = pgm;
2923-
*arg++ = name;
2924-
*arg++ = temp_one->name;
2925-
*arg++ = temp_one->hex;
2926-
*arg++ = temp_one->mode;
2927-
*arg++ = temp_two->name;
2928-
*arg++ = temp_two->hex;
2929-
*arg++ = temp_two->mode;
2922+
argv_array_push(&argv, pgm);
2923+
argv_array_push(&argv, name);
2924+
argv_array_push(&argv, temp_one->name);
2925+
argv_array_push(&argv, temp_one->hex);
2926+
argv_array_push(&argv, temp_one->mode);
2927+
argv_array_push(&argv, temp_two->name);
2928+
argv_array_push(&argv, temp_two->hex);
2929+
argv_array_push(&argv, temp_two->mode);
29302930
if (other) {
2931-
*arg++ = other;
2932-
*arg++ = xfrm_msg;
2931+
argv_array_push(&argv, other);
2932+
argv_array_push(&argv, xfrm_msg);
29332933
}
29342934
} else {
2935-
*arg++ = pgm;
2936-
*arg++ = name;
2935+
argv_array_push(&argv, pgm);
2936+
argv_array_push(&argv, name);
29372937
}
2938-
*arg = NULL;
29392938
fflush(NULL);
29402939

29412940
env[0] = env_counter;
@@ -2944,8 +2943,9 @@ static void run_external_diff(const char *pgm,
29442943
env[1] = env_total;
29452944
snprintf(env_total, sizeof(env_total), "GIT_DIFF_PATH_TOTAL=%d", q->nr);
29462945

2947-
retval = run_command_v_opt_cd_env(spawn_arg, RUN_USING_SHELL, NULL, env);
2946+
retval = run_command_v_opt_cd_env(argv.argv, RUN_USING_SHELL, NULL, env);
29482947
remove_tempfile();
2948+
argv_array_clear(&argv);
29492949
if (retval) {
29502950
fprintf(stderr, "external diff died, stopping at %s.\n", name);
29512951
exit(1);

0 commit comments

Comments
 (0)