Skip to content

Commit 44e5471

Browse files
rscharfegitster
authored andcommitted
apply: check git diffs for invalid file modes
An empty string as mode specification is accepted silently by git apply, as Vegard Nossum found out using AFL. It's interpreted as zero. Reject such bogus file modes, and only accept ones consisting exclusively of octal digits. Reported-by: Vegard Nossum <[email protected]> Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4269974 commit 44e5471

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

apply.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,20 +1011,27 @@ static int gitdiff_newname(struct apply_state *state,
10111011
DIFF_NEW_NAME);
10121012
}
10131013

1014+
static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
1015+
{
1016+
char *end;
1017+
*mode = strtoul(line, &end, 8);
1018+
if (end == line || !isspace(*end))
1019+
return error(_("invalid mode on line %d: %s"), linenr, line);
1020+
return 0;
1021+
}
1022+
10141023
static int gitdiff_oldmode(struct apply_state *state,
10151024
const char *line,
10161025
struct patch *patch)
10171026
{
1018-
patch->old_mode = strtoul(line, NULL, 8);
1019-
return 0;
1027+
return parse_mode_line(line, state->linenr, &patch->old_mode);
10201028
}
10211029

10221030
static int gitdiff_newmode(struct apply_state *state,
10231031
const char *line,
10241032
struct patch *patch)
10251033
{
1026-
patch->new_mode = strtoul(line, NULL, 8);
1027-
return 0;
1034+
return parse_mode_line(line, state->linenr, &patch->new_mode);
10281035
}
10291036

10301037
static int gitdiff_delete(struct apply_state *state,
@@ -1138,7 +1145,7 @@ static int gitdiff_index(struct apply_state *state,
11381145
memcpy(patch->new_sha1_prefix, line, len);
11391146
patch->new_sha1_prefix[len] = 0;
11401147
if (*ptr == ' ')
1141-
patch->old_mode = strtoul(ptr+1, NULL, 8);
1148+
return gitdiff_oldmode(state, ptr + 1, patch);
11421149
return 0;
11431150
}
11441151

t/t4129-apply-samemode.sh

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ test_expect_success setup '
1313
echo modified >file &&
1414
git diff --stat -p >patch-0.txt &&
1515
chmod +x file &&
16-
git diff --stat -p >patch-1.txt
16+
git diff --stat -p >patch-1.txt &&
17+
sed "s/^\(new mode \).*/\1/" <patch-1.txt >patch-empty-mode.txt &&
18+
sed "s/^\(new mode \).*/\1garbage/" <patch-1.txt >patch-bogus-mode.txt
1719
'
1820

1921
test_expect_success FILEMODE 'same mode (no index)' '
@@ -59,4 +61,16 @@ test_expect_success FILEMODE 'mode update (index only)' '
5961
git ls-files -s file | grep "^100755"
6062
'
6163

64+
test_expect_success FILEMODE 'empty mode is rejected' '
65+
git reset --hard &&
66+
test_must_fail git apply patch-empty-mode.txt 2>err &&
67+
test_i18ngrep "invalid mode" err
68+
'
69+
70+
test_expect_success FILEMODE 'bogus mode is rejected' '
71+
git reset --hard &&
72+
test_must_fail git apply patch-bogus-mode.txt 2>err &&
73+
test_i18ngrep "invalid mode" err
74+
'
75+
6276
test_done

0 commit comments

Comments
 (0)