fmt-merge-msg: plug small leak of commit buffer
[gitweb.git] / pretty.c
index 962e82be8633217b811a8c8c87b892721b35f662..915bd1e2e96a165c05e8a67523c759be8f376c2b 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -40,7 +40,7 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c
        const char *fmt;
        int i;
 
-       if (prefixcmp(var, "pretty."))
+       if (!starts_with(var, "pretty."))
                return 0;
 
        name = var + strlen("pretty.");
@@ -67,7 +67,7 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c
        commit_format->name = xstrdup(name);
        commit_format->format = CMIT_FMT_USERFORMAT;
        git_config_string(&fmt, var, value);
-       if (!prefixcmp(fmt, "format:") || !prefixcmp(fmt, "tformat:")) {
+       if (starts_with(fmt, "format:") || starts_with(fmt, "tformat:")) {
                commit_format->is_tformat = fmt[0] == 't';
                fmt = strchr(fmt, ':') + 1;
        } else if (strchr(fmt, '%'))
@@ -115,7 +115,7 @@ static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
        for (i = 0; i < commit_formats_len; i++) {
                size_t match_len;
 
-               if (prefixcmp(commit_formats[i].name, sought))
+               if (!starts_with(commit_formats[i].name, sought))
                        continue;
 
                match_len = strlen(commit_formats[i].name);
@@ -151,7 +151,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)
                rev->commit_format = CMIT_FMT_DEFAULT;
                return;
        }
-       if (!prefixcmp(arg, "format:") || !prefixcmp(arg, "tformat:")) {
+       if (starts_with(arg, "format:") || starts_with(arg, "tformat:")) {
                save_user_format(rev, strchr(arg, ':') + 1, arg[0] == 't');
                return;
        }
@@ -397,12 +397,18 @@ static const char *show_ident_date(const struct ident_split *ident,
                                   enum date_mode mode)
 {
        unsigned long date = 0;
-       int tz = 0;
+       long tz = 0;
 
        if (ident->date_begin && ident->date_end)
                date = strtoul(ident->date_begin, NULL, 10);
-       if (ident->tz_begin && ident->tz_end)
-               tz = strtol(ident->tz_begin, NULL, 10);
+       if (date_overflows(date))
+               date = 0;
+       else {
+               if (ident->tz_begin && ident->tz_end)
+                       tz = strtol(ident->tz_begin, NULL, 10);
+               if (tz >= INT_MAX || tz <= INT_MIN)
+                       tz = 0;
+       }
        return show_date(date, tz, mode);
 }
 
@@ -549,14 +555,13 @@ static char *get_header(const struct commit *commit, const char *msg,
        const char *line = msg;
 
        while (line) {
-               const char *eol = strchr(line, '\n'), *next;
+               const char *eol = strchrnul(line, '\n'), *next;
 
                if (line == eol)
                        return NULL;
-               if (!eol) {
+               if (!*eol) {
                        warning("malformed commit (header is missing newline): %s",
                                sha1_to_hex(commit->object.sha1));
-                       eol = line + strlen(line);
                        next = NULL;
                } else
                        next = eol + 1;
@@ -601,29 +606,16 @@ static char *replace_encoding_header(char *buf, const char *encoding)
        return strbuf_detach(&tmp, NULL);
 }
 
-char *logmsg_reencode(const struct commit *commit,
-                     char **commit_encoding,
-                     const char *output_encoding)
+const char *logmsg_reencode(const struct commit *commit,
+                           char **commit_encoding,
+                           const char *output_encoding)
 {
        static const char *utf8 = "UTF-8";
        const char *use_encoding;
        char *encoding;
-       char *msg = commit->buffer;
+       const char *msg = get_commit_buffer(commit);
        char *out;
 
-       if (!msg) {
-               enum object_type type;
-               unsigned long size;
-
-               msg = read_sha1_file(commit->object.sha1, &type, &size);
-               if (!msg)
-                       die("Cannot read commit object %s",
-                           sha1_to_hex(commit->object.sha1));
-               if (type != OBJ_COMMIT)
-                       die("Expected commit for '%s', got %s",
-                           sha1_to_hex(commit->object.sha1), typename(type));
-       }
-
        if (!output_encoding || !*output_encoding) {
                if (commit_encoding)
                        *commit_encoding =
@@ -647,12 +639,13 @@ char *logmsg_reencode(const struct commit *commit,
                 * Otherwise, we still want to munge the encoding header in the
                 * result, which will be done by modifying the buffer. If we
                 * are using a fresh copy, we can reuse it. But if we are using
-                * the cached copy from commit->buffer, we need to duplicate it
-                * to avoid munging commit->buffer.
+                * the cached copy from get_commit_buffer, we need to duplicate it
+                * to avoid munging the cached copy.
                 */
-               out = msg;
-               if (out == commit->buffer)
-                       out = xstrdup(out);
+               if (msg == get_cached_commit_buffer(commit))
+                       out = xstrdup(msg);
+               else
+                       out = (char *)msg;
        }
        else {
                /*
@@ -662,8 +655,8 @@ char *logmsg_reencode(const struct commit *commit,
                 * copy, we can free it.
                 */
                out = reencode_string(msg, output_encoding, use_encoding);
-               if (out && msg != commit->buffer)
-                       free(msg);
+               if (out)
+                       unuse_commit_buffer(commit, msg);
        }
 
        /*
@@ -682,12 +675,6 @@ char *logmsg_reencode(const struct commit *commit,
        return out ? out : msg;
 }
 
-void logmsg_free(char *msg, const struct commit *commit)
-{
-       if (msg != commit->buffer)
-               free(msg);
-}
-
 static int mailmap_name(const char **email, size_t *email_len,
                        const char **name, size_t *name_len)
 {
@@ -791,7 +778,7 @@ struct format_commit_context {
        struct signature_check signature_check;
        enum flush_type flush_type;
        enum trunc_type truncate;
-       char *message;
+       const char *message;
        char *commit_encoding;
        size_t width, indent1, indent2;
        int auto_color;
@@ -840,10 +827,10 @@ static void parse_commit_header(struct format_commit_context *context)
 
                if (i == eol) {
                        break;
-               } else if (!prefixcmp(msg + i, "author ")) {
+               } else if (starts_with(msg + i, "author ")) {
                        context->author.off = i + 7;
                        context->author.len = eol - i - 7;
-               } else if (!prefixcmp(msg + i, "committer ")) {
+               } else if (starts_with(msg + i, "committer ")) {
                        context->committer.off = i + 10;
                        context->committer.len = eol - i - 10;
                }
@@ -983,7 +970,7 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
 
                if (!end)
                        return 0;
-               if (!prefixcmp(begin, "auto,")) {
+               if (starts_with(begin, "auto,")) {
                        if (!want_color(c->pretty_ctx->color))
                                return end - placeholder + 1;
                        begin += 5;
@@ -994,16 +981,16 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
                strbuf_addstr(sb, color);
                return end - placeholder + 1;
        }
-       if (!prefixcmp(placeholder + 1, "red")) {
+       if (starts_with(placeholder + 1, "red")) {
                strbuf_addstr(sb, GIT_COLOR_RED);
                return 4;
-       } else if (!prefixcmp(placeholder + 1, "green")) {
+       } else if (starts_with(placeholder + 1, "green")) {
                strbuf_addstr(sb, GIT_COLOR_GREEN);
                return 6;
-       } else if (!prefixcmp(placeholder + 1, "blue")) {
+       } else if (starts_with(placeholder + 1, "blue")) {
                strbuf_addstr(sb, GIT_COLOR_BLUE);
                return 5;
-       } else if (!prefixcmp(placeholder + 1, "reset")) {
+       } else if (starts_with(placeholder + 1, "reset")) {
                strbuf_addstr(sb, GIT_COLOR_RESET);
                return 6;
        } else
@@ -1060,11 +1047,11 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
                        end = strchr(start, ')');
                        if (!end || end == start)
                                return 0;
-                       if (!prefixcmp(start, "trunc)"))
+                       if (starts_with(start, "trunc)"))
                                c->truncate = trunc_right;
-                       else if (!prefixcmp(start, "ltrunc)"))
+                       else if (starts_with(start, "ltrunc)"))
                                c->truncate = trunc_left;
-                       else if (!prefixcmp(start, "mtrunc)"))
+                       else if (starts_with(start, "mtrunc)"))
                                c->truncate = trunc_middle;
                        else
                                return 0;
@@ -1089,7 +1076,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
        /* these are independent of the commit */
        switch (placeholder[0]) {
        case 'C':
-               if (!prefixcmp(placeholder + 1, "(auto)")) {
+               if (starts_with(placeholder + 1, "(auto)")) {
                        c->auto_color = 1;
                        return 7; /* consumed 7 bytes, "C(auto)" */
                } else {
@@ -1526,7 +1513,7 @@ void format_commit_message(const struct commit *commit,
        }
 
        free(context.commit_encoding);
-       logmsg_free(context.message, commit);
+       unuse_commit_buffer(commit, context.message);
        free(context.signature_check.gpg_output);
        free(context.signature_check.signer);
 }
@@ -1556,7 +1543,7 @@ static void pp_header(struct pretty_print_context *pp,
                        continue;
                }
 
-               if (!prefixcmp(line, "parent ")) {
+               if (starts_with(line, "parent ")) {
                        if (linelen != 48)
                                die("bad parent line in commit");
                        continue;
@@ -1580,11 +1567,11 @@ static void pp_header(struct pretty_print_context *pp,
                 * FULL shows both authors but not dates.
                 * FULLER shows both authors and dates.
                 */
-               if (!prefixcmp(line, "author ")) {
+               if (starts_with(line, "author ")) {
                        strbuf_grow(sb, linelen + 80);
                        pp_user_info(pp, "Author", sb, line + 7, encoding);
                }
-               if (!prefixcmp(line, "committer ") &&
+               if (starts_with(line, "committer ") &&
                    (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
                        strbuf_grow(sb, linelen + 80);
                        pp_user_info(pp, "Commit", sb, line + 10, encoding);
@@ -1695,7 +1682,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
        unsigned long beginning_of_body;
        int indent = 4;
        const char *msg;
-       char *reencoded;
+       const char *reencoded;
        const char *encoding;
        int need_8bit_cte = pp->need_8bit_cte;
 
@@ -1762,7 +1749,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
        if (pp->fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
                strbuf_addch(sb, '\n');
 
-       logmsg_free(reencoded, commit);
+       unuse_commit_buffer(commit, reencoded);
 }
 
 void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,