https://github.com/git/git
Revision e1e12e97ac73ded85f7d000da1063a774b3cc14f authored by Patrick Steinhardt on 01 December 2022, 14:45:36 UTC, committed by Junio C Hamano on 05 December 2022, 06:14:16 UTC
Attributes have a field that tracks the position in the `all_attrs`
array they're stored inside. This field gets set via `hashmap_get_size`
when adding the attribute to the global map of attributes. But while the
field is of type `int`, the value returned by `hashmap_get_size` is an
`unsigned int`. It can thus happen that the value overflows, where we
would now dereference teh `all_attrs` array at an out-of-bounds value.

We do have a sanity check for this overflow via an assert that verifies
the index matches the new hashmap's size. But asserts are not a proper
mechanism to detect against any such overflows as they may not in fact
be compiled into production code.

Fix this by using an `unsigned int` to track the index and convert the
assert to a call `die()`.

Reported-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 447ac90
Raw File
Tip revision: e1e12e97ac73ded85f7d000da1063a774b3cc14f authored by Patrick Steinhardt on 01 December 2022, 14:45:36 UTC
attr: fix integer overflow with more than INT_MAX macros
Tip revision: e1e12e9
line-log.h
#ifndef LINE_LOG_H
#define LINE_LOG_H

#include "diffcore.h"

struct rev_info;
struct commit;

/* A range [start,end].  Lines are numbered starting at 0, and the
 * ranges include start but exclude end. */
struct range {
	long start, end;
};

/* A set of ranges.  The ranges must always be disjoint and sorted. */
struct range_set {
	unsigned int alloc, nr;
	struct range *ranges;
};

/* A diff, encoded as the set of pre- and post-image ranges where the
 * files differ. A pair of ranges corresponds to a hunk. */
struct diff_ranges {
	struct range_set parent;
	struct range_set target;
};

void range_set_init(struct range_set *, size_t prealloc);
void range_set_release(struct range_set *);
/* Range includes start; excludes end */
void range_set_append_unsafe(struct range_set *, long start, long end);
/* New range must begin at or after end of last added range */
void range_set_append(struct range_set *, long start, long end);
/*
 * In-place pass of sorting and merging the ranges in the range set,
 * to sort and make the ranges disjoint.
 */
void sort_and_merge_range_set(struct range_set *);

/* Linked list of interesting files and their associated ranges.  The
 * list must be kept sorted by path.
 *
 * For simplicity, even though this is highly redundant, each
 * line_log_data owns its 'path'.
 */
struct line_log_data {
	struct line_log_data *next;
	char *path;
	struct range_set ranges;
	struct diff_filepair *pair;
	struct diff_ranges diff;
};

void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args);

int line_log_filter(struct rev_info *rev);
int line_log_process_ranges_arbitrary_commit(struct rev_info *rev,
						    struct commit *commit);

int line_log_print(struct rev_info *rev, struct commit *commit);

#endif /* LINE_LOG_H */
back to top