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 <infthi.inbox@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Apr 19, 2014 at 15:17 UTC
82fbf269b9994d172719b2d456db5ef8453b323d
1 file changed
+16
-16
diff.c
+16
-16
@@ -16,6 +16,7 @@
16
#include "submodule.h"
17
#include "ll-merge.h"
18
#include "string-list.h"
19
+#include "argv-array.h"
20
21
#ifdef NO_FAST_WORKING_DIRECTORY
22
#define FAST_WORKING_DIRECTORY 0
@@ -2906,9 +2907,8 @@ static void run_external_diff(const char *pgm,
2907
int complete_rewrite,
2908
struct diff_options *o)
2909
{
2909
- const char *spawn_arg[10];
2910
+ struct argv_array argv = ARGV_ARRAY_INIT;
2911
int retval;
2911
- const char **arg = &spawn_arg[0];
2912
struct diff_queue_struct *q = &diff_queued_diff;
2913
const char *env[3] = { NULL };
2914
char env_counter[50];
@@ -2919,23 +2919,22 @@ static void run_external_diff(const char *pgm,
2919
const char *othername = (other ? other : name);
2920
temp_one = prepare_temp_file(name, one);
2921
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);
2930
if (other) {
2931
- *arg++ = other;
2932
- *arg++ = xfrm_msg;
2931
+ argv_array_push(&argv, other);
2932
+ argv_array_push(&argv, xfrm_msg);
2933
}
2934
} else {
2935
- *arg++ = pgm;
2936
- *arg++ = name;
2935
+ argv_array_push(&argv, pgm);
2936
+ argv_array_push(&argv, name);
2937
}
2938
- *arg = NULL;
2938
fflush(NULL);
2939
2940
env[0] = env_counter;
@@ -2944,8 +2943,9 @@ static void run_external_diff(const char *pgm,
2943
env[1] = env_total;
2944
snprintf(env_total, sizeof(env_total), "GIT_DIFF_PATH_TOTAL=%d", q->nr);
2945
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);
2947
remove_tempfile();
2948
+ argv_array_clear(&argv);
2949
if (retval) {
2950
fprintf(stderr, "external diff died, stopping at %s.\n", name);
2951
exit(1);