Commit 385a70bea7e7ebf291f0dd06053d7e28c2223f13

Kano 2013-07-06T19:15:59

make all statline overflow safe

diff --git a/cgminer.c b/cgminer.c
index 58c939f..99c5dd3 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -1944,15 +1944,6 @@ static bool curses_active_locked(void)
 }
 #endif
 
-void tailsprintf(char *f, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	vsprintf(f + strlen(f), fmt, ap);
-	va_end(ap);
-}
-
 /* Convert a uint64_t value into a truncated string for displaying with its
  * associated suitable for Mega, Giga etc. Buf array needs to be long enough */
 static void suffix_string(uint64_t val, char *buf, int sigdigits)
@@ -2010,7 +2001,7 @@ static void suffix_string(uint64_t val, char *buf, int sigdigits)
 	}
 }
 
-static void get_statline(char *buf, struct cgpu_info *cgpu)
+static void get_statline(char *buf, size_t bufsiz, struct cgpu_info *cgpu)
 {
 	char displayed_hashes[16], displayed_rolling[16];
 	uint64_t dh64, dr64;
@@ -2035,8 +2026,8 @@ static void get_statline(char *buf, struct cgpu_info *cgpu)
 	suffix_string(dr64, displayed_rolling, 4);
 
 	sprintf(buf, "%s%d ", cgpu->drv->name, cgpu->device_id);
-	cgpu->drv->get_statline_before(buf, cgpu);
-	tailsprintf(buf, "(%ds):%s (avg):%sh/s | A:%.0f R:%.0f HW:%d WU:%.1f/m",
+	cgpu->drv->get_statline_before(buf, bufsiz, cgpu);
+	tailsprintf(buf, bufsiz, "(%ds):%s (avg):%sh/s | A:%.0f R:%.0f HW:%d WU:%.1f/m",
 		opt_log_interval,
 		displayed_rolling,
 		displayed_hashes,
@@ -2044,7 +2035,7 @@ static void get_statline(char *buf, struct cgpu_info *cgpu)
 		cgpu->diff_rejected,
 		cgpu->hw_errors,
 		wu);
-	cgpu->drv->get_statline(buf, cgpu);
+	cgpu->drv->get_statline(buf, bufsiz, cgpu);
 }
 
 static void text_print_status(int thr_id)
@@ -2054,7 +2045,7 @@ static void text_print_status(int thr_id)
 
 	cgpu = get_thr_cgpu(thr_id);
 	if (cgpu) {
-		get_statline(logline, cgpu);
+		get_statline(logline, sizeof(logline), cgpu);
 		printf("%s\n", logline);
 	}
 }
@@ -2143,7 +2134,7 @@ static void curses_print_devstatus(struct cgpu_info *cgpu, int count)
 	wmove(statuswin,devcursor + count, 0);
 	wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id);
 	logline[0] = '\0';
-	cgpu->drv->get_statline_before(logline, cgpu);
+	cgpu->drv->get_statline_before(logline, sizeof(logline), cgpu);
 	wprintw(statuswin, "%s", logline);
 
 	dh64 = (double)cgpu->total_mhashes / dev_runtime * 1000000ull;
@@ -2179,7 +2170,7 @@ static void curses_print_devstatus(struct cgpu_info *cgpu, int count)
 			wuwidth + 2, wu);
 
 	logline[0] = '\0';
-	cgpu->drv->get_statline(logline, cgpu);
+	cgpu->drv->get_statline(logline, sizeof(logline), cgpu);
 	wprintw(statuswin, "%s", logline);
 
 	wclrtoeol(statuswin);
@@ -2642,7 +2633,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
 	if (!want_per_device_stats) {
 		char logline[256];
 
-		get_statline(logline, cgpu);
+		get_statline(logline, sizeof(logline), cgpu);
 		applog(LOG_INFO, "%s", logline);
 	}
 
@@ -4693,7 +4684,7 @@ static void hashmeter(int thr_id, struct timeval *diff,
 
 				cgpu->last_message_tv = now;
 
-				get_statline(logline, cgpu);
+				get_statline(logline, sizeof(logline), cgpu);
 				if (!curses_active) {
 					printf("%s          \r", logline);
 					fflush(stdout);
@@ -6643,7 +6634,7 @@ static void log_print_status(struct cgpu_info *cgpu)
 {
 	char logline[255];
 
-	get_statline(logline, cgpu);
+	get_statline(logline, sizeof(logline), cgpu);
 	applog(LOG_WARNING, "%s", logline);
 }
 
@@ -7023,12 +7014,12 @@ static void noop_reinit_device(struct cgpu_info __maybe_unused *cgpu)
 {
 }
 
-void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu)
+void blank_get_statline_before(char *buf, size_t bufsiz, struct cgpu_info __maybe_unused *cgpu)
 {
-	tailsprintf(buf, "               | ");
+	tailsprintf(buf, bufsiz, "               | ");
 }
 
-static void noop_get_statline(char __maybe_unused *buf, struct cgpu_info __maybe_unused *cgpu)
+static void noop_get_statline(char __maybe_unused *buf, size_t __maybe_unused bufsiz, struct cgpu_info __maybe_unused *cgpu)
 {
 }
 
diff --git a/driver-avalon.c b/driver-avalon.c
index d6aaa4d..d9606ac 100644
--- a/driver-avalon.c
+++ b/driver-avalon.c
@@ -1146,7 +1146,7 @@ static void avalon_update_temps(struct cgpu_info *avalon, struct avalon_info *in
 	}
 }
 
-static void get_avalon_statline_before(char *buf, struct cgpu_info *avalon)
+static void get_avalon_statline_before(char *buf, size_t bufsiz, struct cgpu_info *avalon)
 {
 	struct avalon_info *info = avalon->device_data;
 	int lowfan = 10000;
@@ -1157,7 +1157,7 @@ static void get_avalon_statline_before(char *buf, struct cgpu_info *avalon)
 	if (info->fan2 >= 0 && info->fan2 < lowfan)
 		lowfan = info->fan2;
 
-	tailsprintf(buf, "%2d/%3dC %04dR | ", info->temp0, info->temp2, lowfan);
+	tailsprintf(buf, bufsiz, "%2d/%3dC %04dR | ", info->temp0, info->temp2, lowfan);
 }
 
 /* We use a replacement algorithm to only remove references to work done from
diff --git a/driver-bflsc.c b/driver-bflsc.c
index 2c23978..f3800c0 100644
--- a/driver-bflsc.c
+++ b/driver-bflsc.c
@@ -1235,7 +1235,7 @@ static void bflsc_detect(void)
 	usb_detect(&bflsc_drv, bflsc_detect_one);
 }
 
-static void get_bflsc_statline_before(char *buf, struct cgpu_info *bflsc)
+static void get_bflsc_statline_before(char *buf, size_t bufsiz, struct cgpu_info *bflsc)
 {
 	struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
 	float temp = 0;
@@ -1253,7 +1253,7 @@ static void get_bflsc_statline_before(char *buf, struct cgpu_info *bflsc)
 	}
 	rd_unlock(&(sc_info->stat_lock));
 
-	tailsprintf(buf, " max%3.0fC %4.2fV | ", temp, vcc1);
+	tailsprintf(buf, bufsiz, " max%3.0fC %4.2fV | ", temp, vcc1);
 }
 
 static void flush_one_dev(struct cgpu_info *bflsc, int dev)
diff --git a/driver-bitforce.c b/driver-bitforce.c
index 3306170..a2d19b5 100644
--- a/driver-bitforce.c
+++ b/driver-bitforce.c
@@ -294,15 +294,16 @@ static void bitforce_detect(void)
 	usb_detect(&bitforce_drv, bitforce_detect_one);
 }
 
-static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)
+static void get_bitforce_statline_before(char *buf, size_t bufsiz, struct cgpu_info *bitforce)
 {
 	float gt = bitforce->temp;
 
 	if (gt > 0)
-		tailsprintf(buf, "%5.1fC ", gt);
+		tailsprintf(buf, bufsiz, "%5.1fC ", gt);
 	else
-		tailsprintf(buf, "       ", gt);
-	tailsprintf(buf, "        | ");
+		tailsprintf(buf, bufsiz, "       ");
+
+	tailsprintf(buf, bufsiz, "        | ");
 }
 
 static bool bitforce_thread_prepare(struct thr_info *thr)
diff --git a/driver-modminer.c b/driver-modminer.c
index 50488e8..37cb02e 100644
--- a/driver-modminer.c
+++ b/driver-modminer.c
@@ -741,16 +741,12 @@ static bool modminer_fpga_init(struct thr_info *thr)
 	return true;
 }
 
-static void get_modminer_statline_before(char *buf, struct cgpu_info *modminer)
+static void get_modminer_statline_before(char *buf, size_t bufsiz, struct cgpu_info *modminer)
 {
-	char info[64];
-
-	sprintf(info, " %s%.1fC %3uMHz  | ",
+	tailsprintf(buf, bufsiz, " %s%.1fC %3uMHz  | ",
 			(modminer->temp < 10) ? " " : "",
 			modminer->temp,
 			(unsigned int)(modminer->clock));
-
-	strcat(buf, info);
 }
 
 static bool modminer_start_work(struct thr_info *thr, struct work *work)
diff --git a/driver-opencl.c b/driver-opencl.c
index 9bb7b1f..4f5ee69 100644
--- a/driver-opencl.c
+++ b/driver-opencl.c
@@ -52,7 +52,6 @@ extern bool have_opencl;
 
 extern void *miner_thread(void *userdata);
 extern int dev_from_id(int thr_id);
-extern void tailsprintf(char *f, const char *fmt, ...);
 extern void decay_time(double *f, double fadd);
 
 /**********************************************/
@@ -667,24 +666,24 @@ retry:
 				if (temp != -1)
 					sprintf(logline, "%.1f C  ", temp);
 				if (fanspeed != -1 || fanpercent != -1) {
-					tailsprintf(logline, "F: ");
+					tailsprintf(logline, sizeof(logline), "F: ");
 					if (fanpercent != -1)
-						tailsprintf(logline, "%d%% ", fanpercent);
+						tailsprintf(logline, sizeof(logline), "%d%% ", fanpercent);
 					if (fanspeed != -1)
-						tailsprintf(logline, "(%d RPM) ", fanspeed);
-					tailsprintf(logline, " ");
+						tailsprintf(logline, sizeof(logline), "(%d RPM) ", fanspeed);
+					tailsprintf(logline, sizeof(logline), " ");
 				}
 				if (engineclock != -1)
-					tailsprintf(logline, "E: %d MHz  ", engineclock);
+					tailsprintf(logline, sizeof(logline), "E: %d MHz  ", engineclock);
 				if (memclock != -1)
-					tailsprintf(logline, "M: %d Mhz  ", memclock);
+					tailsprintf(logline, sizeof(logline), "M: %d Mhz  ", memclock);
 				if (vddc != -1)
-					tailsprintf(logline, "V: %.3fV  ", vddc);
+					tailsprintf(logline, sizeof(logline), "V: %.3fV  ", vddc);
 				if (activity != -1)
-					tailsprintf(logline, "A: %d%%  ", activity);
+					tailsprintf(logline, sizeof(logline), "A: %d%%  ", activity);
 				if (powertune != -1)
-					tailsprintf(logline, "P: %d%%", powertune);
-				tailsprintf(logline, "\n");
+					tailsprintf(logline, sizeof(logline), "P: %d%%", powertune);
+				tailsprintf(logline, sizeof(logline), "\n");
 				_wlog(logline);
 			}
 		}
@@ -1271,7 +1270,7 @@ static void reinit_opencl_device(struct cgpu_info *gpu)
 }
 
 #ifdef HAVE_ADL
-static void get_opencl_statline_before(char *buf, struct cgpu_info *gpu)
+static void get_opencl_statline_before(char *buf, size_t bufsiz, struct cgpu_info *gpu)
 {
 	if (gpu->has_adl) {
 		int gpuid = gpu->device_id;
@@ -1280,25 +1279,25 @@ static void get_opencl_statline_before(char *buf, struct cgpu_info *gpu)
 		int gp;
 
 		if (gt != -1)
-			tailsprintf(buf, "%5.1fC ", gt);
+			tailsprintf(buf, bufsiz, "%5.1fC ", gt);
 		else
-			tailsprintf(buf, "       ", gt);
+			tailsprintf(buf, bufsiz, "       ", gt);
 		if (gf != -1)
 			// show invalid as 9999
-			tailsprintf(buf, "%4dRPM ", gf > 9999 ? 9999 : gf);
+			tailsprintf(buf, bufsiz, "%4dRPM ", gf > 9999 ? 9999 : gf);
 		else if ((gp = gpu_fanpercent(gpuid)) != -1)
-			tailsprintf(buf, "%3d%%    ", gp);
+			tailsprintf(buf, bufsiz, "%3d%%    ", gp);
 		else
-			tailsprintf(buf, "        ");
-		tailsprintf(buf, "| ");
+			tailsprintf(buf, bufsiz, "        ");
+		tailsprintf(buf, bufsiz, "| ");
 	} else
 		gpu->drv->get_statline_before = &blank_get_statline_before;
 }
 #endif
 
-static void get_opencl_statline(char *buf, struct cgpu_info *gpu)
+static void get_opencl_statline(char *buf, size_t bufsiz, struct cgpu_info *gpu)
 {
-	tailsprintf(buf, " I:%2d", gpu->intensity);
+	tailsprintf(buf, bufsiz, " I:%2d", gpu->intensity);
 }
 
 struct opencl_thread_data {
diff --git a/driver-ztex.c b/driver-ztex.c
index 0938726..ba6d8cf 100644
--- a/driver-ztex.c
+++ b/driver-ztex.c
@@ -362,11 +362,11 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work,
 	return noncecnt;
 }
 
-static void ztex_statline_before(char *buf, struct cgpu_info *cgpu)
+static void ztex_statline_before(char *buf, size_t bufsiz, struct cgpu_info *cgpu)
 {
 	if (cgpu->deven == DEV_ENABLED) {
-		tailsprintf(buf, "%s-%d | ", cgpu->device_ztex->snString, cgpu->device_ztex->fpgaNum+1);
-		tailsprintf(buf, "%0.1fMHz | ", cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1));
+		tailsprintf(buf, bufsiz, "%s-%d | ", cgpu->device_ztex->snString, cgpu->device_ztex->fpgaNum+1);
+		tailsprintf(buf, bufsiz, "%0.1fMHz | ", cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1));
 	}
 }
 
diff --git a/miner.h b/miner.h
index 68577f9..c054325 100644
--- a/miner.h
+++ b/miner.h
@@ -294,7 +294,7 @@ struct gpu_adl {
 };
 #endif
 
-extern void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu);
+extern void blank_get_statline_before(char *buf, size_t bufsiz, struct cgpu_info __maybe_unused *cgpu);
 
 struct api_data;
 struct thr_info;
@@ -311,8 +311,8 @@ struct device_drv {
 
 	// Device-specific functions
 	void (*reinit_device)(struct cgpu_info *);
-	void (*get_statline_before)(char *, struct cgpu_info *);
-	void (*get_statline)(char *, struct cgpu_info *);
+	void (*get_statline_before)(char *, size_t, struct cgpu_info *);
+	void (*get_statline)(char *, size_t, struct cgpu_info *);
 	struct api_data *(*get_api_stats)(struct cgpu_info *);
 	bool (*get_stats)(struct cgpu_info *);
 	void (*identify_device)(struct cgpu_info *); // e.g. to flash a led
@@ -1272,6 +1272,18 @@ struct modminer_fpga_state {
 };
 #endif
 
+#define TAILBUFSIZ 64
+
+#define tailsprintf(buf, bufsiz, fmt, ...) do { \
+	char tmp13[TAILBUFSIZ]; \
+	size_t len13, buflen = strlen(buf); \
+	snprintf(tmp13, sizeof(tmp13), fmt, ##__VA_ARGS__); \
+	len13 = strlen(tmp13); \
+	if ((buflen + len13) >= bufsiz) \
+		quit(1, "tailsprintf buffer overflow in %s %s line %d", __FILE__, __func__, __LINE__); \
+	strcat(buf, tmp13); \
+} while (0)
+
 extern void get_datestamp(char *, struct timeval *);
 extern void inc_hw_errors(struct thr_info *thr);
 extern bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce);
@@ -1280,7 +1292,6 @@ extern struct work *__find_work_bymidstate(struct work *que, char *midstate, siz
 extern struct work *find_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
 extern void work_completed(struct cgpu_info *cgpu, struct work *work);
 extern void hash_queued_work(struct thr_info *mythr);
-extern void tailsprintf(char *f, const char *fmt, ...);
 extern void _wlog(const char *str);
 extern void _wlogprint(const char *str);
 extern int curses_int(const char *query);