Blame SOURCES/kexec-tools-2.0.15-makedumpfile-Use-integer-arithmetics-for-th.patch

cf4a81
From c6b79cbc990b3b4933730205f58812fb44b6fcd5 Mon Sep 17 00:00:00 2001
cf4a81
From: Petr Tesarik <ptesarik@suse.cz>
cf4a81
Date: Tue, 10 Apr 2018 20:39:00 +0900
cf4a81
Subject: [PATCH] [PATCH v2] makedumpfile: Use integer arithmetics for the
cf4a81
 progress bar
cf4a81
cf4a81
Essentially, the estimated remaining time is calculated as:
cf4a81
cf4a81
  elapsed * (100 - progress) / progress
cf4a81
cf4a81
Since the calculation is done with floating point numbers, it had
cf4a81
masked a division by zero (if progress is 0), producing a NaN or
cf4a81
infinity. The following conversion to int produces INT_MIN with GCC
cf4a81
on major platforms, which originally overflowed the eta buffer. This
cf4a81
bug was fixed by commit e5f96e79d69a1d295f19130da00ec6514d28a8ae,
cf4a81
but conversion of NaN and infinity is undefined behaviour in ISO C,
cf4a81
plus the corresponding output is still wrong, e.g.:
cf4a81
cf4a81
Copying data                                      : [  0.0 %] /  eta:
cf4a81
-9223372036854775808s
cf4a81
cf4a81
Most importantly, using the FPU for a progress bar is overkill.
cf4a81
Since the progress percentage is reported with one decimal digit
cf4a81
following the decimal point, it can be stored as an integer tenths
cf4a81
of a percent.
cf4a81
cf4a81
Second, the estimated time can be calculated in milliseconds. Up to
cf4a81
49 days can be represented this way even on 32-bit platforms. Note
cf4a81
that delta.tv_usec can be ignored in the subtraction, because the
cf4a81
resulting eta is printed as seconds, so elapsed microseconds are
cf4a81
irrelevant.
cf4a81
cf4a81
Last but not least, the original buffer overflow was probably caused
cf4a81
by the wrong assumption that integers < 100 can be interpreted with
cf4a81
less than 3 ASCII characters, but that's not true for signed
cf4a81
integers. To make eta_to_human_short() a bit safer, use an unsigned
cf4a81
integer type.
cf4a81
cf4a81
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
cf4a81
---
cf4a81
 print_info.c | 43 ++++++++++++++++++++-----------------------
cf4a81
 1 file changed, 20 insertions(+), 23 deletions(-)
cf4a81
cf4a81
diff --git a/makedumpfile-1.6.2/print_info.c b/makedumpfile-1.6.2/print_info.c
cf4a81
index 09e215a..6bfcd11 100644
cf4a81
--- a/makedumpfile-1.6.2/print_info.c
cf4a81
+++ b/makedumpfile-1.6.2/print_info.c
cf4a81
@@ -16,8 +16,6 @@
cf4a81
 #include "print_info.h"
cf4a81
 #include <time.h>
cf4a81
 #include <string.h>
cf4a81
-#include <stdint.h>
cf4a81
-#include <inttypes.h>
cf4a81
 
cf4a81
 #define PROGRESS_MAXLEN		"50"
cf4a81
 
cf4a81
@@ -354,21 +352,18 @@ static void calc_delta(struct timeval *tv_start, struct timeval *delta)
cf4a81
 }
cf4a81
 
cf4a81
 /* produce less than 12 bytes on msg */
cf4a81
-static int eta_to_human_short (int64_t secs, char* msg, int maxsize)
cf4a81
+static int eta_to_human_short (unsigned long secs, char* msg)
cf4a81
 {
cf4a81
 	strcpy(msg, "eta: ");
cf4a81
 	msg += strlen("eta: ");
cf4a81
 	if (secs < 100)
cf4a81
-		snprintf(msg, maxsize, "%"PRId64"s", secs);
cf4a81
+		sprintf(msg, "%lus", secs);
cf4a81
 	else if (secs < 100 * 60)
cf4a81
-		snprintf(msg, maxsize, "%"PRId64"m""%"PRId64"s",
cf4a81
-			secs / 60, secs % 60);
cf4a81
+		sprintf(msg, "%lum%lus", secs / 60, secs % 60);
cf4a81
 	else if (secs < 48 * 3600)
cf4a81
-		snprintf(msg, maxsize, "%"PRId64"h""%"PRId64"m",
cf4a81
-			secs / 3600, (secs / 60) % 60);
cf4a81
+		sprintf(msg, "%luh%lum", secs / 3600, (secs / 60) % 60);
cf4a81
 	else if (secs < 100 * 86400)
cf4a81
-		snprintf(msg, maxsize, "%"PRId64"d""%"PRId64"h",
cf4a81
-			secs / 86400, (secs / 3600) % 24);
cf4a81
+		sprintf(msg, "%lud%luh", secs / 86400, (secs / 3600) % 24);
cf4a81
 	else
cf4a81
 		sprintf(msg, ">2day");
cf4a81
 	return 0;
cf4a81
@@ -378,37 +373,39 @@ static int eta_to_human_short (int64_t secs, char* msg, int maxsize)
cf4a81
 void
cf4a81
 print_progress(const char *msg, unsigned long current, unsigned long end, struct timeval *start)
cf4a81
 {
cf4a81
-	float progress;
cf4a81
+	unsigned progress;	/* in promilles (tenths of a percent) */
cf4a81
 	time_t tm;
cf4a81
 	static time_t last_time = 0;
cf4a81
 	static unsigned int lapse = 0;
cf4a81
 	static const char *spinner = "/|\\-";
cf4a81
 	struct timeval delta;
cf4a81
-	int64_t eta;
cf4a81
-	char eta_msg[32] = " ";
cf4a81
+	unsigned long eta;
cf4a81
+	char eta_msg[16] = " ";
cf4a81
 
cf4a81
 	if (current < end) {
cf4a81
 		tm = time(NULL);
cf4a81
 		if (tm - last_time < 1)
cf4a81
 			return;
cf4a81
 		last_time = tm;
cf4a81
-		progress = (float)current * 100 / end;
cf4a81
+		progress = current * 1000 / end;
cf4a81
 	} else
cf4a81
-		progress = 100;
cf4a81
+		progress = 1000;
cf4a81
 
cf4a81
-	if (start != NULL) {
cf4a81
+	if (start != NULL && progress != 0) {
cf4a81
 		calc_delta(start, &delta);
cf4a81
-		eta = delta.tv_sec + delta.tv_usec / 1e6;
cf4a81
-		eta = (100 - progress) * eta / progress;
cf4a81
-		eta_to_human_short(eta, eta_msg, sizeof(eta_msg));
cf4a81
+		eta = 1000 * delta.tv_sec + delta.tv_usec / 1000;
cf4a81
+		eta = eta / progress - delta.tv_sec;
cf4a81
+		eta_to_human_short(eta, eta_msg);
cf4a81
 	}
cf4a81
 	if (flag_ignore_r_char) {
cf4a81
-		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%5.1f %%] %c  %16s\n",
cf4a81
-			     msg, progress, spinner[lapse % 4], eta_msg);
cf4a81
+		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3u.%u %%] %c  %16s\n",
cf4a81
+			     msg, progress / 10, progress % 10,
cf4a81
+			     spinner[lapse % 4], eta_msg);
cf4a81
 	} else {
cf4a81
 		PROGRESS_MSG("\r");
cf4a81
-		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%5.1f %%] %c  %16s",
cf4a81
-			     msg, progress, spinner[lapse % 4], eta_msg);
cf4a81
+		PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3u.%u %%] %c  %16s",
cf4a81
+			     msg, progress / 10, progress % 10,
cf4a81
+			     spinner[lapse % 4], eta_msg);
cf4a81
 	}
cf4a81
 	lapse++;
cf4a81
 }
cf4a81
-- 
cf4a81
2.9.5
cf4a81