]> git.ipfire.org Git - thirdparty/git.git/blobdiff - apply.c
apply: improve error messages when reading patch
[thirdparty/git.git] / apply.c
diff --git a/apply.c b/apply.c
index 5258314e9bc416ac0a422157ae5c79bcc89d5ffe..567bca96e7a5c3aacac87095661cf157bee06fb3 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -125,7 +125,7 @@ void clear_apply_state(struct apply_state *state)
        /* &state->fn_table is cleared at the end of apply_patch() */
 }
 
-static void mute_routine(const char *msg, va_list params)
+static void mute_routine(const char *msg UNUSED, va_list params UNUSED)
 {
        /* do nothing */
 }
@@ -386,11 +386,22 @@ static void say_patch_name(FILE *output, const char *fmt, struct patch *patch)
 
 #define SLOP (16)
 
+/*
+ * apply.c isn't equipped to handle arbitrarily large patches, because
+ * it intermingles `unsigned long` with `int` for the type used to store
+ * buffer lengths.
+ *
+ * Only process patches that are just shy of 1 GiB large in order to
+ * avoid any truncation or overflow issues.
+ */
+#define MAX_APPLY_SIZE (1024UL * 1024 * 1023)
+
 static int read_patch_file(struct strbuf *sb, int fd)
 {
        if (strbuf_read(sb, fd, 0) < 0)
-               return error_errno("git apply: failed to read");
-
+               return error_errno(_("failed to read patch"));
+       else if (sb->len >= MAX_APPLY_SIZE)
+               return error(_("patch too large"));
        /*
         * Make sure that we have some slop in the buffer
         * so that we can do speculative "memcmp" etc, and
@@ -892,9 +903,9 @@ static int parse_traditional_patch(struct apply_state *state,
        return 0;
 }
 
-static int gitdiff_hdrend(struct gitdiff_data *state,
-                         const char *line,
-                         struct patch *patch)
+static int gitdiff_hdrend(struct gitdiff_data *state UNUSED,
+                         const char *line UNUSED,
+                         struct patch *patch UNUSED)
 {
        return 1;
 }
@@ -1044,7 +1055,7 @@ static int gitdiff_renamedst(struct gitdiff_data *state,
        return 0;
 }
 
-static int gitdiff_similarity(struct gitdiff_data *state,
+static int gitdiff_similarity(struct gitdiff_data *state UNUSED,
                              const char *line,
                              struct patch *patch)
 {
@@ -1054,7 +1065,7 @@ static int gitdiff_similarity(struct gitdiff_data *state,
        return 0;
 }
 
-static int gitdiff_dissimilarity(struct gitdiff_data *state,
+static int gitdiff_dissimilarity(struct gitdiff_data *state UNUSED,
                                 const char *line,
                                 struct patch *patch)
 {
@@ -1104,9 +1115,9 @@ static int gitdiff_index(struct gitdiff_data *state,
  * This is normal for a diff that doesn't change anything: we'll fall through
  * into the next diff. Tell the parser to break out.
  */
-static int gitdiff_unrecognized(struct gitdiff_data *state,
-                               const char *line,
-                               struct patch *patch)
+static int gitdiff_unrecognized(struct gitdiff_data *state UNUSED,
+                               const char *line UNUSED,
+                               struct patch *patch UNUSED)
 {
        return 1;
 }
@@ -2903,7 +2914,7 @@ static int apply_one_fragment(struct apply_state *state,
                        break;
                case ' ':
                        if (plen && (ws_rule & WS_BLANK_AT_EOF) &&
-                           ws_blank_line(patch + 1, plen, ws_rule))
+                           ws_blank_line(patch + 1, plen))
                                is_blank_context = 1;
                        /* fallthrough */
                case '-':
@@ -2932,7 +2943,7 @@ static int apply_one_fragment(struct apply_state *state,
                                      (first == '+' ? 0 : LINE_COMMON));
                        if (first == '+' &&
                            (ws_rule & WS_BLANK_AT_EOF) &&
-                           ws_blank_line(patch + 1, plen, ws_rule))
+                           ws_blank_line(patch + 1, plen))
                                added_blank_line = 1;
                        break;
                case '@': case '\\':
@@ -3274,11 +3285,11 @@ static struct patch *in_fn_table(struct apply_state *state, const char *name)
 {
        struct string_list_item *item;
 
-       if (name == NULL)
+       if (!name)
                return NULL;
 
        item = string_list_lookup(&state->fn_table, name);
-       if (item != NULL)
+       if (item)
                return (struct patch *)item->util;
 
        return NULL;
@@ -3318,7 +3329,7 @@ static void add_to_fn_table(struct apply_state *state, struct patch *patch)
         * This should cover the cases for normal diffs,
         * file creations and copies
         */
-       if (patch->new_name != NULL) {
+       if (patch->new_name) {
                item = string_list_insert(&state->fn_table, patch->new_name);
                item->util = patch;
        }