Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 8597ea3

Browse files
peffgitster
authored andcommitted
commit: record buffer length in cache
Most callsites which use the commit buffer try to use the cached version attached to the commit, rather than re-reading from disk. Unfortunately, that interface provides only a pointer to the NUL-terminated buffer, with no indication of the original length. For the most part, this doesn't matter. People do not put NULs in their commit messages, and the log code is happy to treat it all as a NUL-terminated string. However, some code paths do care. For example, when checking signatures, we want to be very careful that we verify all the bytes to avoid malicious trickery. This patch just adds an optional "size" out-pointer to get_commit_buffer and friends. The existing callers all pass NULL (there did not seem to be any obvious sites where we could avoid an immediate strlen() call, though perhaps with some further refactoring we could). Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent c1b3c71 commit 8597ea3

16 files changed

+68
-38
lines changed

builtin/blame.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1998,6 +1998,18 @@ static void append_merge_parents(struct commit_list **tail)
19981998
strbuf_release(&line);
19991999
}
20002000

2001+
/*
2002+
* This isn't as simple as passing sb->buf and sb->len, because we
2003+
* want to transfer ownership of the buffer to the commit (so we
2004+
* must use detach).
2005+
*/
2006+
static void set_commit_buffer_from_strbuf(struct commit *c, struct strbuf *sb)
2007+
{
2008+
size_t len;
2009+
void *buf = strbuf_detach(sb, &len);
2010+
set_commit_buffer(c, buf, len);
2011+
}
2012+
20012013
/*
20022014
* Prepare a dummy commit that represents the work tree (or staged) item.
20032015
* Note that annotating work tree item never works in the reverse.
@@ -2046,7 +2058,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
20462058
ident, ident, path,
20472059
(!contents_from ? path :
20482060
(!strcmp(contents_from, "-") ? "standard input" : contents_from)));
2049-
set_commit_buffer(commit, strbuf_detach(&msg, NULL));
2061+
set_commit_buffer_from_strbuf(commit, &msg);
20502062

20512063
if (!contents_from || strcmp("-", contents_from)) {
20522064
struct stat st;

builtin/fast-export.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
289289
rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
290290

291291
parse_commit_or_die(commit);
292-
commit_buffer = get_commit_buffer(commit);
292+
commit_buffer = get_commit_buffer(commit, NULL);
293293
author = strstr(commit_buffer, "\nauthor ");
294294
if (!author)
295295
die ("Could not find author in commit %s",

builtin/fmt-merge-msg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ static void record_person(int which, struct string_list *people,
236236
const char *field;
237237

238238
field = (which == 'a') ? "\nauthor " : "\ncommitter ";
239-
buffer = get_commit_buffer(commit);
239+
buffer = get_commit_buffer(commit, NULL);
240240
name = strstr(buffer, field);
241241
if (!name)
242242
return;

builtin/index-pack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
774774
}
775775
if (obj->type == OBJ_COMMIT) {
776776
struct commit *commit = (struct commit *) obj;
777-
if (detach_commit_buffer(commit) != data)
777+
if (detach_commit_buffer(commit, NULL) != data)
778778
die("BUG: parse_object_buffer transmogrified our buffer");
779779
}
780780
obj->flags |= FLAG_CHECKED;

builtin/log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
919919
&need_8bit_cte);
920920

921921
for (i = 0; !need_8bit_cte && i < nr; i++) {
922-
const char *buf = get_commit_buffer(list[i]);
922+
const char *buf = get_commit_buffer(list[i], NULL);
923923
if (has_non_ascii(buf))
924924
need_8bit_cte = 1;
925925
unuse_commit_buffer(list[i], buf);

builtin/rev-list.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static void show_commit(struct commit *commit, void *data)
106106
else
107107
putchar('\n');
108108

109-
if (revs->verbose_header && get_cached_commit_buffer(commit)) {
109+
if (revs->verbose_header && get_cached_commit_buffer(commit, NULL)) {
110110
struct strbuf buf = STRBUF_INIT;
111111
struct pretty_print_context ctx = {0};
112112
ctx.abbrev = revs->abbrev;

commit.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -245,22 +245,31 @@ int unregister_shallow(const unsigned char *sha1)
245245
return 0;
246246
}
247247

248-
define_commit_slab(buffer_slab, void *);
248+
struct commit_buffer {
249+
void *buffer;
250+
unsigned long size;
251+
};
252+
define_commit_slab(buffer_slab, struct commit_buffer);
249253
static struct buffer_slab buffer_slab = COMMIT_SLAB_INIT(1, buffer_slab);
250254

251-
void set_commit_buffer(struct commit *commit, void *buffer)
255+
void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
252256
{
253-
*buffer_slab_at(&buffer_slab, commit) = buffer;
257+
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
258+
v->buffer = buffer;
259+
v->size = size;
254260
}
255261

256-
const void *get_cached_commit_buffer(const struct commit *commit)
262+
const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
257263
{
258-
return *buffer_slab_at(&buffer_slab, commit);
264+
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
265+
if (sizep)
266+
*sizep = v->size;
267+
return v->buffer;
259268
}
260269

261-
const void *get_commit_buffer(const struct commit *commit)
270+
const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
262271
{
263-
const void *ret = get_cached_commit_buffer(commit);
272+
const void *ret = get_cached_commit_buffer(commit, sizep);
264273
if (!ret) {
265274
enum object_type type;
266275
unsigned long size;
@@ -271,29 +280,38 @@ const void *get_commit_buffer(const struct commit *commit)
271280
if (type != OBJ_COMMIT)
272281
die("expected commit for %s, got %s",
273282
sha1_to_hex(commit->object.sha1), typename(type));
283+
if (sizep)
284+
*sizep = size;
274285
}
275286
return ret;
276287
}
277288

278289
void unuse_commit_buffer(const struct commit *commit, const void *buffer)
279290
{
280-
void *cached = *buffer_slab_at(&buffer_slab, commit);
281-
if (cached != buffer)
291+
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
292+
if (v->buffer != buffer)
282293
free((void *)buffer);
283294
}
284295

285296
void free_commit_buffer(struct commit *commit)
286297
{
287-
void **b = buffer_slab_at(&buffer_slab, commit);
288-
free(*b);
289-
*b = NULL;
298+
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
299+
free(v->buffer);
300+
v->buffer = NULL;
301+
v->size = 0;
290302
}
291303

292-
const void *detach_commit_buffer(struct commit *commit)
304+
const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
293305
{
294-
void **b = buffer_slab_at(&buffer_slab, commit);
295-
void *ret = *b;
296-
*b = NULL;
306+
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
307+
void *ret;
308+
309+
ret = v->buffer;
310+
if (sizep)
311+
*sizep = v->size;
312+
313+
v->buffer = NULL;
314+
v->size = 0;
297315
return ret;
298316
}
299317

@@ -374,7 +392,7 @@ int parse_commit(struct commit *item)
374392
}
375393
ret = parse_commit_buffer(item, buffer, size);
376394
if (save_commit_buffer && !ret) {
377-
set_commit_buffer(item, buffer);
395+
set_commit_buffer(item, buffer, size);
378396
return 0;
379397
}
380398
free(buffer);
@@ -589,7 +607,7 @@ static void record_author_date(struct author_date_slab *author_date,
589607
struct commit *commit)
590608
{
591609
const char *buf, *line_end, *ident_line;
592-
const char *buffer = get_commit_buffer(commit);
610+
const char *buffer = get_commit_buffer(commit, NULL);
593611
struct ident_split ident;
594612
char *date_end;
595613
unsigned long date;

commit.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,20 @@ void parse_commit_or_die(struct commit *item);
5454
* Associate an object buffer with the commit. The ownership of the
5555
* memory is handed over to the commit, and must be free()-able.
5656
*/
57-
void set_commit_buffer(struct commit *, void *buffer);
57+
void set_commit_buffer(struct commit *, void *buffer, unsigned long size);
5858

5959
/*
6060
* Get any cached object buffer associated with the commit. Returns NULL
6161
* if none. The resulting memory should not be freed.
6262
*/
63-
const void *get_cached_commit_buffer(const struct commit *);
63+
const void *get_cached_commit_buffer(const struct commit *, unsigned long *size);
6464

6565
/*
6666
* Get the commit's object contents, either from cache or by reading the object
6767
* from disk. The resulting memory should not be modified, and must be given
6868
* to unuse_commit_buffer when the caller is done.
6969
*/
70-
const void *get_commit_buffer(const struct commit *);
70+
const void *get_commit_buffer(const struct commit *, unsigned long *size);
7171

7272
/*
7373
* Tell the commit subsytem that we are done with a particular commit buffer.
@@ -86,7 +86,7 @@ void free_commit_buffer(struct commit *);
8686
* Disassociate any cached object buffer from the commit, but do not free it.
8787
* The buffer (or NULL, if none) is returned.
8888
*/
89-
const void *detach_commit_buffer(struct commit *);
89+
const void *detach_commit_buffer(struct commit *, unsigned long *sizep);
9090

9191
/* Find beginning and length of commit subject. */
9292
int find_commit_subject(const char *commit_buffer, const char **subject);

fsck.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer,
339339

340340
static int fsck_commit(struct commit *commit, fsck_error error_func)
341341
{
342-
const char *buffer = get_commit_buffer(commit);
342+
const char *buffer = get_commit_buffer(commit, NULL);
343343
int ret = fsck_commit_buffer(commit, buffer, error_func);
344344
unuse_commit_buffer(commit, buffer);
345345
return ret;

log-tree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ void show_log(struct rev_info *opt)
588588
show_mergetag(opt, commit);
589589
}
590590

591-
if (!get_cached_commit_buffer(commit))
591+
if (!get_cached_commit_buffer(commit, NULL))
592592
return;
593593

594594
if (opt->show_notes) {

0 commit comments

Comments
 (0)