Thread (3 messages) 3 messages, 3 authors, 2016-06-15

[PATCH] diff: use 64-bit integers for diffstat calculations

flat view
DORMANTno replies

From: Jeff King <hidden>
Date: 2016-06-15 22:48:39
Subsystem: the rest · Maintainer: Linus Torvalds

On Fri, Apr 16, 2010 at 05:02:01PM +0200, Tomas Carnecky wrote:
quoted
commit 6afe3d3c889daa92bd79956c4bb733eb5cb408dc
Author: Heikki Orsila[off-list ref]
Date:   2010-04-16 16:54:52 +0300

    test commit

 0 |  Bin 0 ->  -2146435072 bytes
 1 |  Bin 0 ->  -2146435072 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)
Yep, bug is also in the latest version (1.7.0.5). The code uses 'int'
instead of something big enough to hold the size of your files.
Yuck, we use "unsigned int" for the actual storage, and then convert to
a regular "int" in some other places. I think we should just do this:

-- >8 --
Subject: [PATCH] diff: use 64-bit integers for diffstat calculations

The diffstat "added" and "changed" fields generally store
line counts; however, for binary files, they store file
sizes. Since we store and print these values as ints, a
diffstat on a file larger than 2G can show a negative size.
Instead, let's explicitly use 64-bit integers.

Signed-off-by: Jeff King <redacted>
---
 diff.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/diff.c b/diff.c
index 7effdac..54933cc 100644
--- a/diff.c
+++ b/diff.c
@@ -936,7 +936,7 @@ struct diffstat_t {
 		unsigned is_unmerged:1;
 		unsigned is_binary:1;
 		unsigned is_renamed:1;
-		unsigned int added, deleted;
+		uint64_t added, deleted;
 	} **files;
 };
 
@@ -1028,7 +1028,7 @@ static void fill_print_name(struct diffstat_file *file)
 static void show_stats(struct diffstat_t *data, struct diff_options *options)
 {
 	int i, len, add, del, adds = 0, dels = 0;
-	int max_change = 0, max_len = 0;
+	uint64_t max_change = 0, max_len = 0;
 	int total_files = data->nr;
 	int width, name_width;
 	const char *reset, *set, *add_c, *del_c;
@@ -1057,7 +1057,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 
 	for (i = 0; i < data->nr; i++) {
 		struct diffstat_file *file = data->files[i];
-		int change = file->added + file->deleted;
+		uint64_t change = file->added + file->deleted;
 		fill_print_name(file);
 		len = strlen(file->print_name);
 		if (max_len < len)
@@ -1085,8 +1085,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 	for (i = 0; i < data->nr; i++) {
 		const char *prefix = "";
 		char *name = data->files[i]->print_name;
-		int added = data->files[i]->added;
-		int deleted = data->files[i]->deleted;
+		uint64_t added = data->files[i]->added;
+		uint64_t deleted = data->files[i]->deleted;
 		int name_len;
 
 		/*
@@ -1107,9 +1107,11 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		if (data->files[i]->is_binary) {
 			show_name(options->file, prefix, name, len);
 			fprintf(options->file, "  Bin ");
-			fprintf(options->file, "%s%d%s", del_c, deleted, reset);
+			fprintf(options->file, "%s%"PRIu64"%s",
+				del_c, deleted, reset);
 			fprintf(options->file, " -> ");
-			fprintf(options->file, "%s%d%s", add_c, added, reset);
+			fprintf(options->file, "%s%"PRIu64"%s",
+				add_c, added, reset);
 			fprintf(options->file, " bytes");
 			fprintf(options->file, "\n");
 			continue;
@@ -1138,7 +1140,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 			del = scale_linear(del, width, max_change);
 		}
 		show_name(options->file, prefix, name, len);
-		fprintf(options->file, "%5d%s", added + deleted,
+		fprintf(options->file, "%5"PRIu64"%s", added + deleted,
 				added + deleted ? " " : "");
 		show_graph(options->file, '+', add, add_c, reset);
 		show_graph(options->file, '-', del, del_c, reset);
@@ -1188,7 +1190,8 @@ static void show_numstat(struct diffstat_t *data, struct diff_options *options)
 			fprintf(options->file, "-\t-\t");
 		else
 			fprintf(options->file,
-				"%d\t%d\t", file->added, file->deleted);
+				"%"PRIu64"\t%"PRIu64"\t",
+				file->added, file->deleted);
 		if (options->line_termination) {
 			fill_print_name(file);
 			if (!file->is_renamed)
-- 
1.7.1.rc1.277.g2c4c9
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help