Browse Source

Merge pull request #462 from kanoi/master

various type checking and overflow checking
kanoi 12 years ago
parent
commit
3245ec7ad5
11 changed files with 219 additions and 196 deletions
  1. 112 93
      cgminer.c
  2. 2 5
      driver-avalon.c
  3. 27 10
      driver-bflsc.c
  4. 7 10
      driver-bitforce.c
  5. 2 7
      driver-icarus.c
  6. 4 12
      driver-modminer.c
  7. 22 23
      driver-opencl.c
  8. 3 7
      driver-ztex.c
  9. 1 1
      logging.c
  10. 16 5
      miner.h
  11. 23 23
      usbutils.c

+ 112 - 93
cgminer.c

@@ -358,13 +358,13 @@ static bool should_run(void)
 	return true;
 }
 
-void get_datestamp(char *f, struct timeval *tv)
+void get_datestamp(char *f, size_t fsiz, struct timeval *tv)
 {
 	struct tm *tm;
 
 	const time_t tmp_time = tv->tv_sec;
 	tm = localtime(&tmp_time);
-	sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d]",
+	snprintf(f, fsiz, "[%d-%02d-%02d %02d:%02d:%02d]",
 		tm->tm_year + 1900,
 		tm->tm_mon + 1,
 		tm->tm_mday,
@@ -373,13 +373,13 @@ void get_datestamp(char *f, struct timeval *tv)
 		tm->tm_sec);
 }
 
-void get_timestamp(char *f, struct timeval *tv)
+static void get_timestamp(char *f, size_t fsiz, struct timeval *tv)
 {
 	struct tm *tm;
 
 	const time_t tmp_time = tv->tv_sec;
 	tm = localtime(&tmp_time);
-	sprintf(f, "[%02d:%02d:%02d]",
+	snprintf(f, fsiz, "[%02d:%02d:%02d]",
 		tm->tm_hour,
 		tm->tm_min,
 		tm->tm_sec);
@@ -1311,7 +1311,7 @@ static char *parse_config(json_t *config, bool fileconf)
 					applog(LOG_ERR, "Invalid config option %s: %s", p, err);
 					fileconf_load = -1;
 				} else {
-					sprintf(err_buf, "Parsing JSON option %s: %s",
+					snprintf(err_buf, sizeof(err_buf), "Parsing JSON option %s: %s",
 						p, err);
 					return err_buf;
 				}
@@ -1334,6 +1334,7 @@ static char *load_config(const char *arg, void __maybe_unused *unused)
 	json_error_t err;
 	json_t *config;
 	char *json_error;
+	size_t siz;
 
 	if (!cnfbuf)
 		cnfbuf = strdup(arg);
@@ -1347,11 +1348,12 @@ static char *load_config(const char *arg, void __maybe_unused *unused)
 	config = json_load_file(arg, &err);
 #endif
 	if (!json_is_object(config)) {
-		json_error = malloc(JSON_LOAD_ERROR_LEN + strlen(arg) + strlen(err.text));
+		siz = JSON_LOAD_ERROR_LEN + strlen(arg) + strlen(err.text);
+		json_error = malloc(siz);
 		if (!json_error)
 			quit(1, "Malloc failure in json error");
 
-		sprintf(json_error, JSON_LOAD_ERROR, arg, err.text);
+		snprintf(json_error, siz, JSON_LOAD_ERROR, arg, err.text);
 		return json_error;
 	}
 
@@ -1944,18 +1946,9 @@ 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)
+static void suffix_string(uint64_t val, char *buf, size_t bufsiz, int sigdigits)
 {
 	const double  dkilo = 1000.0;
 	const uint64_t kilo = 1000ull;
@@ -1971,26 +1964,26 @@ static void suffix_string(uint64_t val, char *buf, int sigdigits)
 	if (val >= exa) {
 		val /= peta;
 		dval = (double)val / dkilo;
-		sprintf(suffix, "E");
+		strcpy(suffix, "E");
 	} else if (val >= peta) {
 		val /= tera;
 		dval = (double)val / dkilo;
-		sprintf(suffix, "P");
+		strcpy(suffix, "P");
 	} else if (val >= tera) {
 		val /= giga;
 		dval = (double)val / dkilo;
-		sprintf(suffix, "T");
+		strcpy(suffix, "T");
 	} else if (val >= giga) {
 		val /= mega;
 		dval = (double)val / dkilo;
-		sprintf(suffix, "G");
+		strcpy(suffix, "G");
 	} else if (val >= mega) {
 		val /= kilo;
 		dval = (double)val / dkilo;
-		sprintf(suffix, "M");
+		strcpy(suffix, "M");
 	} else if (val >= kilo) {
 		dval = (double)val / dkilo;
-		sprintf(suffix, "K");
+		strcpy(suffix, "K");
 	} else {
 		dval = val;
 		decimal = false;
@@ -1998,19 +1991,19 @@ static void suffix_string(uint64_t val, char *buf, int sigdigits)
 
 	if (!sigdigits) {
 		if (decimal)
-			sprintf(buf, "%.3g%s", dval, suffix);
+			snprintf(buf, bufsiz, "%.3g%s", dval, suffix);
 		else
-			sprintf(buf, "%d%s", (unsigned int)dval, suffix);
+			snprintf(buf, bufsiz, "%d%s", (unsigned int)dval, suffix);
 	} else {
 		/* Always show sigdigits + 1, padded on right with zeroes
 		 * followed by suffix */
 		int ndigits = sigdigits - 1 - (dval > 0.0 ? floor(log10(dval)) : 0);
 
-		sprintf(buf, "%*.*f%s", sigdigits + 1, ndigits, dval, suffix);
+		snprintf(buf, bufsiz, "%*.*f%s", sigdigits + 1, ndigits, dval, suffix);
 	}
 }
 
-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;
@@ -2031,12 +2024,12 @@ static void get_statline(char *buf, struct cgpu_info *cgpu)
 
 	dh64 = (double)cgpu->total_mhashes / dev_runtime * 1000000ull;
 	dr64 = (double)cgpu->rolling * 1000000ull;
-	suffix_string(dh64, displayed_hashes, 4);
-	suffix_string(dr64, displayed_rolling, 4);
+	suffix_string(dh64, displayed_hashes, sizeof(displayed_hashes), 4);
+	suffix_string(dr64, displayed_rolling, sizeof(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",
+	snprintf(buf, bufsiz, "%s%d ", cgpu->drv->name, cgpu->device_id);
+	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 +2037,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,44 +2047,56 @@ 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);
 	}
 }
 
 #ifdef HAVE_CURSES
+#define CURBUFSIZ 256
+#define cg_mvwprintw(win, y, x, fmt, ...) do { \
+	char tmp42[CURBUFSIZ]; \
+	snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
+	mvwprintw(win, y, x, "%s", tmp42); \
+} while (0)
+#define cg_wprintw(win, fmt, ...) do { \
+	char tmp42[CURBUFSIZ]; \
+	snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
+	wprintw(win, "%s", tmp42); \
+} while (0)
+
 /* Must be called with curses mutex lock held and curses_active */
 static void curses_print_status(void)
 {
 	struct pool *pool = current_pool();
 
 	wattron(statuswin, A_BOLD);
-	mvwprintw(statuswin, 0, 0, " " PACKAGE " version " VERSION " - Started: %s", datestamp);
+	cg_mvwprintw(statuswin, 0, 0, " " PACKAGE " version " VERSION " - Started: %s", datestamp);
 	wattroff(statuswin, A_BOLD);
 	mvwhline(statuswin, 1, 0, '-', 80);
-	mvwprintw(statuswin, 2, 0, " %s", statusline);
+	cg_mvwprintw(statuswin, 2, 0, " %s", statusline);
 	wclrtoeol(statuswin);
-	mvwprintw(statuswin, 3, 0, " ST: %d  SS: %d  NB: %d  LW: %d  GF: %d  RF: %d",
+	cg_mvwprintw(statuswin, 3, 0, " ST: %d  SS: %d  NB: %d  LW: %d  GF: %d  RF: %d",
 		total_staged(), total_stale, new_blocks,
 		local_work, total_go, total_ro);
 	wclrtoeol(statuswin);
 	if ((pool_strategy == POOL_LOADBALANCE  || pool_strategy == POOL_BALANCE) && total_pools > 1) {
-		mvwprintw(statuswin, 4, 0, " Connected to multiple pools with%s LP",
+		cg_mvwprintw(statuswin, 4, 0, " Connected to multiple pools with%s LP",
 			have_longpoll ? "": "out");
 	} else if (pool->has_stratum) {
-		mvwprintw(statuswin, 4, 0, " Connected to %s diff %s with stratum as user %s",
+		cg_mvwprintw(statuswin, 4, 0, " Connected to %s diff %s with stratum as user %s",
 			pool->sockaddr_url, pool->diff, pool->rpc_user);
 	} else {
-		mvwprintw(statuswin, 4, 0, " Connected to %s diff %s with%s %s as user %s",
+		cg_mvwprintw(statuswin, 4, 0, " Connected to %s diff %s with%s %s as user %s",
 			pool->sockaddr_url, pool->diff, have_longpoll ? "": "out",
 			pool->has_gbt ? "GBT" : "LP", pool->rpc_user);
 	}
 	wclrtoeol(statuswin);
-	mvwprintw(statuswin, 5, 0, " Block: %s...  Diff:%s  Started: %s  Best share: %s   ",
+	cg_mvwprintw(statuswin, 5, 0, " Block: %s...  Diff:%s  Started: %s  Best share: %s   ",
 		  current_hash, block_diff, blocktime, best_share);
 	mvwhline(statuswin, 6, 0, '-', 80);
 	mvwhline(statuswin, statusy - 1, 0, '-', 80);
-	mvwprintw(statuswin, devcursor - 1, 1, "[P]ool management %s[S]ettings [D]isplay options [Q]uit",
+	cg_mvwprintw(statuswin, devcursor - 1, 1, "[P]ool management %s[S]ettings [D]isplay options [Q]uit",
 		have_opencl ? "[G]PU management " : "");
 }
 
@@ -2141,37 +2146,37 @@ static void curses_print_devstatus(struct cgpu_info *cgpu, int count)
 	wu = cgpu->diff1 / dev_runtime * 60;
 
 	wmove(statuswin,devcursor + count, 0);
-	wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id);
+	cg_wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id);
 	logline[0] = '\0';
-	cgpu->drv->get_statline_before(logline, cgpu);
-	wprintw(statuswin, "%s", logline);
+	cgpu->drv->get_statline_before(logline, sizeof(logline), cgpu);
+	cg_wprintw(statuswin, "%s", logline);
 
 	dh64 = (double)cgpu->total_mhashes / dev_runtime * 1000000ull;
 	dr64 = (double)cgpu->rolling * 1000000ull;
-	suffix_string(dh64, displayed_hashes, 4);
-	suffix_string(dr64, displayed_rolling, 4);
+	suffix_string(dh64, displayed_hashes, sizeof(displayed_hashes), 4);
+	suffix_string(dr64, displayed_rolling, sizeof(displayed_rolling), 4);
 
 #ifdef USE_USBUTILS
 	if (cgpu->usbinfo.nodev)
-		wprintw(statuswin, "ZOMBIE");
+		cg_wprintw(statuswin, "ZOMBIE");
 	else
 #endif
 	if (cgpu->status == LIFE_DEAD)
-		wprintw(statuswin, "DEAD  ");
+		cg_wprintw(statuswin, "DEAD  ");
 	else if (cgpu->status == LIFE_SICK)
-		wprintw(statuswin, "SICK  ");
+		cg_wprintw(statuswin, "SICK  ");
 	else if (cgpu->deven == DEV_DISABLED)
-		wprintw(statuswin, "OFF   ");
+		cg_wprintw(statuswin, "OFF   ");
 	else if (cgpu->deven == DEV_RECOVER)
-		wprintw(statuswin, "REST  ");
+		cg_wprintw(statuswin, "REST  ");
 	else
-		wprintw(statuswin, "%6s", displayed_rolling);
+		cg_wprintw(statuswin, "%6s", displayed_rolling);
 	adj_fwidth(cgpu->diff_accepted, &dawidth);
 	adj_fwidth(cgpu->diff_rejected, &drwidth);
 	adj_width(cgpu->hw_errors, &hwwidth);
 	adj_width(wu, &wuwidth);
 
-	wprintw(statuswin, "/%6sh/s | A:%*.0f R:%*.0f HW:%*d WU:%*.1f/m",
+	cg_wprintw(statuswin, "/%6sh/s | A:%*.0f R:%*.0f HW:%*d WU:%*.1f/m",
 			displayed_hashes,
 			dawidth, cgpu->diff_accepted,
 			drwidth, cgpu->diff_rejected,
@@ -2179,8 +2184,8 @@ static void curses_print_devstatus(struct cgpu_info *cgpu, int count)
 			wuwidth + 2, wu);
 
 	logline[0] = '\0';
-	cgpu->drv->get_statline(logline, cgpu);
-	wprintw(statuswin, "%s", logline);
+	cgpu->drv->get_statline(logline, sizeof(logline), cgpu);
+	cg_wprintw(statuswin, "%s", logline);
 
 	wclrtoeol(statuswin);
 }
@@ -2419,7 +2424,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work,
 
 			strcpy(reason, "");
 			if (total_pools > 1)
-				sprintf(where, "pool %d", work->pool->pool_no);
+				snprintf(where, sizeof(where), "pool %d", work->pool->pool_no);
 			else
 				strcpy(where, "");
 
@@ -2574,9 +2579,10 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
 			outhash = bin2hex(rhash + 2, 4);
 		else
 			outhash = bin2hex(rhash + 4, 4);
-		suffix_string(work->share_diff, diffdisp, 0);
-		sprintf(hashshow, "%s Diff %s/%d%s", outhash, diffdisp, intdiff,
-			work->block? " BLOCK!" : "");
+		suffix_string(work->share_diff, diffdisp, sizeof(diffdisp), 0);
+		snprintf(hashshow, sizeof(hashshow), "%s Diff %s/%d%s",
+				outhash, diffdisp, intdiff,
+				work->block? " BLOCK!" : "");
 		free(outhash);
 
 		if (opt_worktime) {
@@ -2601,8 +2607,8 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
 			memcpy(&tm_submit_reply, tm, sizeof(struct tm));
 
 			if (work->clone) {
-				sprintf(workclone, "C:%1.3f",
-					tdiff((struct timeval *)&(work->tv_cloned),
+				snprintf(workclone, sizeof(workclone), "C:%1.3f",
+						tdiff((struct timeval *)&(work->tv_cloned),
 						(struct timeval *)&(work->tv_getwork_reply)));
 			}
 			else
@@ -2611,7 +2617,8 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
 			if (work->work_difficulty < 1)
 				diffplaces = 6;
 
-			sprintf(worktime, " <-%08lx.%08lx M:%c D:%1.*f G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d",
+			snprintf(worktime, sizeof(worktime),
+				" <-%08lx.%08lx M:%c D:%1.*f G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d",
 				(unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 32 : 28])),
 				(unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 28 : 24])),
 				work->getwork_mode, diffplaces, work->work_difficulty,
@@ -2642,7 +2649,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);
 	}
 
@@ -2761,7 +2768,7 @@ static void calc_diff(struct work *work, int known)
 	difficulty = work->work_difficulty;
 
 	pool_stats->last_diff = difficulty;
-	suffix_string((uint64_t)difficulty, work->pool->diff, 0);
+	suffix_string((uint64_t)difficulty, work->pool->diff, sizeof(work->pool->diff), 0);
 
 	if (difficulty == pool_stats->min_diff)
 		pool_stats->min_diff_count++;
@@ -3305,7 +3312,7 @@ static uint64_t share_diff(const struct work *work)
 	if (unlikely(ret > best_diff)) {
 		new_best = true;
 		best_diff = ret;
-		suffix_string(best_diff, best_share, 0);
+		suffix_string(best_diff, best_share, sizeof(best_share), 0);
 	}
 	if (unlikely(ret > work->pool->best_diff))
 		work->pool->best_diff = ret;
@@ -3606,7 +3613,7 @@ static void set_curblock(char *hexstr, unsigned char *hash)
 	current_hash = bin2hex(hash_swap + 2, 8);
 	free(current_fullhash);
 	current_fullhash = bin2hex(block_hash_swap, 32);
-	get_timestamp(blocktime, &block_timeval);
+	get_timestamp(blocktime, sizeof(blocktime), &block_timeval);
 	cg_wunlock(&ch_lock);
 
 	applog(LOG_INFO, "New block: %s... diff %s", current_hash, block_diff);
@@ -3683,7 +3690,7 @@ static void set_blockdiff(const struct work *work)
 
 	previous_diff = current_diff;
 	diff64 = diffone / d64;
-	suffix_string(diff64, block_diff, 0);
+	suffix_string(diff64, block_diff, sizeof(block_diff), 0);
 	current_diff = (double)diffone / (double)d64;
 	if (unlikely(current_diff != previous_diff))
 		applog(LOG_NOTICE, "Network diff set to %s", block_diff);
@@ -4153,7 +4160,7 @@ void zero_bestshare(void)
 
 	best_diff = 0;
 	memset(best_share, 0, 8);
-	suffix_string(best_diff, best_share, 0);
+	suffix_string(best_diff, best_share, sizeof(best_share), 0);
 
 	for (i = 0; i < total_pools; i++) {
 		struct pool *pool = pools[i];
@@ -4530,7 +4537,7 @@ retry:
 		char *str, filename[PATH_MAX], prompt[PATH_MAX + 50];
 
 		default_save_file(filename);
-		sprintf(prompt, "Config filename to write (Enter for default) [%s]", filename);
+		snprintf(prompt, sizeof(prompt), "Config filename to write (Enter for default) [%s]", filename);
 		str = curses_input(prompt);
 		if (strcmp(str, "-1")) {
 			struct stat statbuf;
@@ -4693,7 +4700,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);
@@ -4726,10 +4733,11 @@ static void hashmeter(int thr_id, struct timeval *diff,
 
 	dh64 = (double)total_mhashes_done / total_secs * 1000000ull;
 	dr64 = (double)rolling * 1000000ull;
-	suffix_string(dh64, displayed_hashes, 4);
-	suffix_string(dr64, displayed_rolling, 4);
+	suffix_string(dh64, displayed_hashes, sizeof(displayed_hashes), 4);
+	suffix_string(dr64, displayed_rolling, sizeof(displayed_rolling), 4);
 
-	sprintf(statusline, "%s(%ds):%s (avg):%sh/s | A:%.0f  R:%.0f  HW:%d  WU:%.1f/m",
+	snprintf(statusline, sizeof(statusline),
+		"%s(%ds):%s (avg):%sh/s | A:%.0f  R:%.0f  HW:%d  WU:%.1f/m",
 		want_per_device_stats ? "ALL " : "",
 		opt_log_interval, displayed_rolling, displayed_hashes,
 		total_diff_accepted, total_diff_rejected, hw_errors,
@@ -4752,15 +4760,16 @@ static void stratum_share_result(json_t *val, json_t *res_val, json_t *err_val,
 				 struct stratum_share *sshare)
 {
 	struct work *work = sshare->work;
-	char hashshow[65];
+	char hashshow[64];
 	uint32_t *hash32;
 	char diffdisp[16];
 	int intdiff;
 
 	hash32 = (uint32_t *)(work->hash);
 	intdiff = floor(work->work_difficulty);
-	suffix_string(work->share_diff, diffdisp, 0);
-	sprintf(hashshow, "%08lx Diff %s/%d%s", (unsigned long)htole32(hash32[6]), diffdisp, intdiff,
+	suffix_string(work->share_diff, diffdisp, sizeof (diffdisp), 0);
+	snprintf(hashshow, sizeof(hashshow),
+		"%08lx Diff %s/%d%s", (unsigned long)htole32(hash32[6]), diffdisp, intdiff,
 		work->block? " BLOCK!" : "");
 	share_result(val, res_val, err_val, work, hashshow, false, "");
 }
@@ -5136,7 +5145,8 @@ static void *stratum_sthread(void *userdata)
 		sshare->id = swork_id++;
 		mutex_unlock(&sshare_lock);
 
-		sprintf(s, "{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}",
+		snprintf(s, sizeof(s),
+			"{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}",
 			pool->rpc_user, work->job_id, work->nonce2, work->ntime, noncehex, sshare->id);
 		free(noncehex);
 
@@ -5362,6 +5372,7 @@ retry_stratum:
 		if (pool->hdr_path) {
 			char *copy_start, *hdr_path;
 			bool need_slash = false;
+			size_t siz;
 
 			hdr_path = pool->hdr_path;
 			if (strstr(hdr_path, "://")) {
@@ -5373,13 +5384,14 @@ retry_stratum:
 				if (pool->rpc_url[strlen(pool->rpc_url) - 1] != '/')
 					need_slash = true;
 
-				pool->lp_url = malloc(strlen(pool->rpc_url) + strlen(copy_start) + 2);
+				siz = strlen(pool->rpc_url) + strlen(copy_start) + 2;
+				pool->lp_url = malloc(siz);
 				if (!pool->lp_url) {
 					applog(LOG_ERR, "Malloc failure in pool_active");
 					return false;
 				}
 
-				sprintf(pool->lp_url, "%s%s%s", pool->rpc_url, need_slash ? "/" : "", copy_start);
+				snprintf(pool->lp_url, siz, "%s%s%s", pool->rpc_url, need_slash ? "/" : "", copy_start);
 			}
 		} else
 			pool->lp_url = NULL;
@@ -5582,7 +5594,8 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 	header = calloc(pool->swork.header_len, 1);
 	if (unlikely(!header))
 		quit(1, "Failed to calloc header in gen_stratum_work");
-	sprintf(header, "%s%s%s%s%s%s%s",
+	snprintf(header, pool->swork.header_len,
+		"%s%s%s%s%s%s%s",
 		pool->swork.bbversion,
 		pool->swork.prev_hash,
 		merkle_hash,
@@ -6307,7 +6320,8 @@ retry_pool:
 		 * avoid races */
 		if (pool->has_gbt) {
 			cg_rlock(&pool->gbt_lock);
-			sprintf(lpreq, "{\"id\": 0, \"method\": \"getblocktemplate\", \"params\": "
+			snprintf(lpreq, sizeof(lpreq),
+				"{\"id\": 0, \"method\": \"getblocktemplate\", \"params\": "
 				"[{\"capabilities\": [\"coinbasetxn\", \"workid\", \"coinbase/append\"], "
 				"\"longpollid\": \"%s\"}]}\n", pool->longpollid);
 			cg_runlock(&pool->gbt_lock);
@@ -6574,7 +6588,7 @@ static void *watchdog_thread(void __maybe_unused *userdata)
 
 			gpu = cgpu->device_id;
 			denable = &cgpu->deven;
-			sprintf(dev_str, "%s%d", cgpu->drv->name, gpu);
+			snprintf(dev_str, sizeof(dev_str), "%s%d", cgpu->drv->name, gpu);
 
 #ifdef HAVE_ADL
 			if (adl_active && cgpu->has_adl)
@@ -6643,7 +6657,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);
 }
 
@@ -6820,15 +6834,18 @@ static void *test_pool_thread(void *arg)
  * active it returns false. */
 bool add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass)
 {
+	size_t siz;
+
 	url = get_proxy(url, pool);
 
 	pool->rpc_url = url;
 	pool->rpc_user = user;
 	pool->rpc_pass = pass;
-	pool->rpc_userpass = malloc(strlen(pool->rpc_user) + strlen(pool->rpc_pass) + 2);
+	siz = strlen(pool->rpc_user) + strlen(pool->rpc_pass) + 2;
+	pool->rpc_userpass = malloc(siz);
 	if (!pool->rpc_userpass)
 		quit(1, "Failed to malloc userpass");
-	sprintf(pool->rpc_userpass, "%s:%s", pool->rpc_user, pool->rpc_pass);
+	snprintf(pool->rpc_userpass, siz, "%s:%s", pool->rpc_user, pool->rpc_pass);
 
 	pool->testing = true;
 	pool->idle = true;
@@ -7023,12 +7040,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)
 {
 }
 
@@ -7388,7 +7405,7 @@ int main(int argc, char *argv[])
 	if (unlikely(pthread_cond_init(&gws_cond, NULL)))
 		quit(1, "Failed to pthread_cond_init gws_cond");
 
-	sprintf(packagename, "%s %s", PACKAGE, VERSION);
+	snprintf(packagename, sizeof(packagename), "%s %s", PACKAGE, VERSION);
 
 	handler.sa_handler = &sighandler;
 	handler.sa_flags = 0;
@@ -7619,6 +7636,7 @@ int main(int argc, char *argv[])
 
 	for (i = 0; i < total_pools; i++) {
 		struct pool *pool = pools[i];
+		size_t siz;
 
 		pool->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
 		pool->cgminer_pool_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
@@ -7626,10 +7644,11 @@ int main(int argc, char *argv[])
 		if (!pool->rpc_userpass) {
 			if (!pool->rpc_user || !pool->rpc_pass)
 				quit(1, "No login credentials supplied for pool %u %s", i, pool->rpc_url);
-			pool->rpc_userpass = malloc(strlen(pool->rpc_user) + strlen(pool->rpc_pass) + 2);
+			siz = strlen(pool->rpc_user) + strlen(pool->rpc_pass) + 2;
+			pool->rpc_userpass = malloc(siz);
 			if (!pool->rpc_userpass)
 				quit(1, "Failed to malloc userpass");
-			sprintf(pool->rpc_userpass, "%s:%s", pool->rpc_user, pool->rpc_pass);
+			snprintf(pool->rpc_userpass, siz, "%s:%s", pool->rpc_user, pool->rpc_pass);
 		}
 	}
 	/* Set the currentpool to pool 0 */
@@ -7726,7 +7745,7 @@ begin_bench:
 	
 	cgtime(&total_tv_start);
 	cgtime(&total_tv_end);
-	get_datestamp(datestamp, &total_tv_start);
+	get_datestamp(datestamp, sizeof(datestamp), &total_tv_start);
 
 	// Start threads
 	k = 0;

+ 2 - 5
driver-avalon.c

@@ -985,7 +985,6 @@ static bool avalon_prepare(struct thr_info *thr)
 {
 	struct cgpu_info *avalon = thr->cgpu;
 	struct avalon_info *info = avalon->device_data;
-	struct timeval now;
 
 	free(avalon->works);
 	avalon->works = calloc(info->miner_count * sizeof(struct work *),
@@ -1008,8 +1007,6 @@ static bool avalon_prepare(struct thr_info *thr)
 
 	avalon_init(avalon);
 
-	cgtime(&now);
-	get_datestamp(avalon->init, &now);
 	return true;
 }
 
@@ -1146,7 +1143,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 +1154,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

+ 27 - 10
driver-bflsc.c

@@ -127,6 +127,8 @@ struct bflsc_dev {
 	bool flushed; // are any flushed?
 };
 
+#define QUE_MAX_RESULTS 8
+
 struct bflsc_info {
 	enum driver_version driver_version;
 	pthread_rwlock_t stat_lock;
@@ -150,6 +152,9 @@ struct bflsc_info {
 	int que_noncecount;
 	int que_fld_min;
 	int que_fld_max;
+	int flush_size;
+	// count of given size, [+2] is for any > QUE_MAX_RESULTS
+	uint64_t result_size[QUE_MAX_RESULTS+2];
 };
 
 #define BFLSC_XLINKHDR '@'
@@ -183,12 +188,12 @@ struct QueueJobStructure {
 
 #define QUE_NONCECOUNT_V1 2
 #define QUE_FLD_MIN_V1 3
-#define QUE_FLD_MAX_V1 11
+#define QUE_FLD_MAX_V1 (QUE_MAX_RESULTS+QUE_FLD_MIN_V1)
 
 #define QUE_CHIP_V2 2
 #define QUE_NONCECOUNT_V2 3
 #define QUE_FLD_MIN_V2 4
-#define QUE_FLD_MAX_V2 12
+#define QUE_FLD_MAX_V2 (QUE_MAX_RESULTS+QUE_FLD_MIN_V2)
 
 #define BFLSC_SIGNATURE 0xc1
 #define BFLSC_EOW 0xfe
@@ -1131,6 +1136,8 @@ reinit:
 			sc_info->que_noncecount = QUE_NONCECOUNT_V1;
 			sc_info->que_fld_min = QUE_FLD_MIN_V1;
 			sc_info->que_fld_max = QUE_FLD_MAX_V1;
+			// Only Jalapeno uses 1.0.0
+			sc_info->flush_size = 1;
 			break;
 		case BFLSC_DRV2:
 		case BFLSC_DRVUNDEF:
@@ -1144,6 +1151,8 @@ reinit:
 			sc_info->que_noncecount = QUE_NONCECOUNT_V2;
 			sc_info->que_fld_min = QUE_FLD_MIN_V2;
 			sc_info->que_fld_max = QUE_FLD_MAX_V2;
+			// TODO: this can be reduced to total chip count
+			sc_info->flush_size = 16 * sc_info->sc_count;
 			break;
 	}
 
@@ -1235,7 +1244,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 +1262,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)
@@ -1546,7 +1555,7 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
 	char midstate[MIDSTATE_BYTES], blockdata[MERKLE_BYTES];
 	struct work *work;
 	uint32_t nonce;
-	int i, num;
+	int i, num, x;
 	bool res;
 	char *tmp;
 
@@ -1597,6 +1606,7 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
 	}
 
 	res = false;
+	x = 0;
 	for (i = sc_info->que_fld_min; i < count; i++) {
 		if (strlen(fields[i]) != 8) {
 			tmp = str_text(data);
@@ -1614,12 +1624,16 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
 			wr_unlock(&(sc_info->stat_lock));
 
 			(*nonces)++;
+			x++;
 		}
 	}
 
 	wr_lock(&(sc_info->stat_lock));
 	if (res)
 		sc_info->sc_devs[dev].result_id++;
+	if (x > QUE_MAX_RESULTS)
+		x = QUE_MAX_RESULTS + 1;
+	(sc_info->result_size[x])++;
 	sc_info->sc_devs[dev].work_complete++;
 	sc_info->sc_devs[dev].hashes_unsent += FULLNONCE;
 	// If not flushed (stale)
@@ -1781,7 +1795,6 @@ static bool bflsc_thread_prepare(struct thr_info *thr)
 {
 	struct cgpu_info *bflsc = thr->cgpu;
 	struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
-	struct timeval now;
 
 	if (thr_info_create(&(sc_info->results_thr), NULL, bflsc_get_results, (void *)bflsc)) {
 		applog(LOG_ERR, "%s%i: thread create failed", bflsc->drv->name, bflsc->device_id);
@@ -1789,9 +1802,6 @@ static bool bflsc_thread_prepare(struct thr_info *thr)
 	}
 	pthread_detach(sc_info->results_thr.pth);
 
-	cgtime(&now);
-	get_datestamp(bflsc->init, &now);
-
 	return true;
 }
 
@@ -2047,7 +2057,7 @@ static int64_t bflsc_scanwork(struct thr_info *thr)
 			// Is there any flushed work that can be removed?
 			rd_lock(&(sc_info->stat_lock));
 			if (sc_info->sc_devs[dev].flushed) {
-				if (sc_info->sc_devs[dev].result_id > (sc_info->sc_devs[dev].flush_id + 1))
+				if (sc_info->sc_devs[dev].result_id > (sc_info->sc_devs[dev].flush_id + sc_info->flush_size))
 					cleanup = true;
 			}
 			rd_unlock(&(sc_info->stat_lock));
@@ -2216,6 +2226,7 @@ static struct api_data *bflsc_api_stats(struct cgpu_info *bflsc)
 {
 	struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
 	struct api_data *root = NULL;
+	char buf[256];
 	int i;
 
 //if no x-link ... etc
@@ -2238,6 +2249,12 @@ static struct api_data *bflsc_api_stats(struct cgpu_info *bflsc)
 	root = api_add_uint(root, "Scan Sleep", &(sc_info->scan_sleep_time), true);
 	root = api_add_uint(root, "Results Sleep", &(sc_info->results_sleep_time), true);
 	root = api_add_uint(root, "Work ms", &(sc_info->default_ms_work), true);
+
+	buf[0] = '\0';
+	for (i = 0; i <= QUE_MAX_RESULTS + 1; i++)
+		tailsprintf(buf, sizeof(buf), "%s%"PRIu64, (i > 0) ? "/" : "", sc_info->result_size[i]);
+	root = api_add_string(root, "Result Size", buf, true);
+
 	rd_unlock(&(sc_info->stat_lock));
 
 	i = (int)(sc_info->driver_version);

+ 7 - 10
driver-bitforce.c

@@ -294,24 +294,21 @@ 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)
+static bool bitforce_thread_prepare(__maybe_unused struct thr_info *thr)
 {
-	struct cgpu_info *bitforce = thr->cgpu;
-	struct timeval now;
-
-	cgtime(&now);
-	get_datestamp(bitforce->init, &now);
+//	struct cgpu_info *bitforce = thr->cgpu;
 
 	return true;
 }

+ 2 - 7
driver-icarus.c

@@ -839,14 +839,9 @@ static void icarus_detect()
 	usb_detect(&icarus_drv, icarus_detect_one);
 }
 
-static bool icarus_prepare(struct thr_info *thr)
+static bool icarus_prepare(__maybe_unused struct thr_info *thr)
 {
-	struct cgpu_info *icarus = thr->cgpu;
-
-	struct timeval now;
-
-	cgtime(&now);
-	get_datestamp(icarus->init, &now);
+//	struct cgpu_info *icarus = thr->cgpu;
 
 	return true;
 }

+ 4 - 12
driver-modminer.c

@@ -569,13 +569,9 @@ dame:
 
 static bool modminer_fpga_prepare(struct thr_info *thr)
 {
-	struct cgpu_info *modminer = thr->cgpu;
-	struct timeval now;
-
-	cgtime(&now);
-	get_datestamp(modminer->init, &now);
-
+//	struct cgpu_info *modminer = thr->cgpu;
 	struct modminer_fpga_state *state;
+
 	state = thr->cgpu_data = calloc(1, sizeof(struct modminer_fpga_state));
 	state->shares_to_good = MODMINER_EARLY_UP;
 	state->overheated = false;
@@ -741,16 +737,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)

+ 22 - 23
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);
 			}
 		}
@@ -699,7 +698,7 @@ retry:
 			thr = get_thread(i);
 			if (thr->cgpu != cgpu)
 				continue;
-			get_datestamp(checkin, &thr->last);
+			get_datestamp(checkin, sizeof(checkin), &thr->last);
 			displayed_rolling = thr->rolling;
 			if (!mhash_base)
 				displayed_rolling *= 1000;
@@ -1198,7 +1197,7 @@ select_cgpu:
 	}
 
 	cgtime(&now);
-	get_datestamp(cgpu->init, &now);
+	get_datestamp(cgpu->init, sizeof(cgpu->init), &now);
 
 	for (thr_id = 0; thr_id < mining_threads; ++thr_id) {
 		thr = get_thread(thr_id);
@@ -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 {
@@ -1383,7 +1382,7 @@ static bool opencl_thread_prepare(struct thr_info *thr)
 	}
 	applog(LOG_INFO, "initCl() finished. Found %s", name);
 	cgtime(&now);
-	get_datestamp(cgpu->init, &now);
+	get_datestamp(cgpu->init, sizeof(cgpu->init), &now);
 
 	have_opencl = true;
 

+ 3 - 7
driver-ztex.c

@@ -362,23 +362,19 @@ 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));
 	}
 }
 
 static bool ztex_prepare(struct thr_info *thr)
 {
-	struct timeval now;
 	struct cgpu_info *cgpu = thr->cgpu;
 	struct libztex_device *ztex = cgpu->device_ztex;
 
-	cgtime(&now);
-	get_datestamp(cgpu->init, &now);
-
 	ztex_selectFpga(ztex);
 	if (libztex_configureFpga(ztex) != 0) {
 		libztex_resetFpga(ztex);

+ 1 - 1
logging.c

@@ -63,7 +63,7 @@ void _applog(int prio, const char *str)
 		const time_t tmp_time = tv.tv_sec;
 		tm = localtime(&tmp_time);
 
-		sprintf(datetime, " [%d-%02d-%02d %02d:%02d:%02d] ",
+		snprintf(datetime, sizeof(datetime), " [%d-%02d-%02d %02d:%02d:%02d] ",
 			tm->tm_year + 1900,
 			tm->tm_mon + 1,
 			tm->tm_mday,

+ 16 - 5
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,7 +1272,19 @@ struct modminer_fpga_state {
 };
 #endif
 
-extern void get_datestamp(char *, struct timeval *);
+#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 *, size_t, 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);
 extern struct work *get_queued(struct cgpu_info *cgpu);
@@ -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);

+ 23 - 23
usbutils.c

@@ -712,7 +712,7 @@ static bool setgetdes(ssize_t count, libusb_device *dev, struct libusb_device_ha
 
 	err = libusb_set_configuration(handle, cd);
 	if (err) {
-		sprintf(tmp, EOL "  ** dev %d: Failed to set config descriptor to %d, err %d",
+		snprintf(tmp, sizeof(tmp), EOL "  ** dev %d: Failed to set config descriptor to %d, err %d",
 				(int)count, cd, err);
 		append(buf, tmp, off, len);
 		return false;
@@ -720,13 +720,13 @@ static bool setgetdes(ssize_t count, libusb_device *dev, struct libusb_device_ha
 
 	err = libusb_get_active_config_descriptor(dev, config);
 	if (err) {
-		sprintf(tmp, EOL "  ** dev %d: Failed to get active config descriptor set to %d, err %d",
+		snprintf(tmp, sizeof(tmp), EOL "  ** dev %d: Failed to get active config descriptor set to %d, err %d",
 				(int)count, cd, err);
 		append(buf, tmp, off, len);
 		return false;
 	}
 
-	sprintf(tmp, EOL "  ** dev %d: Set & Got active config descriptor to %d, err %d",
+	snprintf(tmp, sizeof(tmp), EOL "  ** dev %d: Set & Got active config descriptor to %d, err %d",
 			(int)count, cd, err);
 	append(buf, tmp, off, len);
 	return true;
@@ -749,7 +749,7 @@ static void usb_full(ssize_t *count, libusb_device *dev, char **buf, size_t *off
 
 	err = libusb_get_device_descriptor(dev, &desc);
 	if (opt_usb_list_all && err) {
-		sprintf(tmp, EOL ".USB dev %d: Failed to get descriptor, err %d",
+		snprintf(tmp, sizeof(tmp), EOL ".USB dev %d: Failed to get descriptor, err %d",
 					(int)(++(*count)), err);
 		append(buf, tmp, off, len);
 		return;
@@ -775,11 +775,11 @@ static void usb_full(ssize_t *count, libusb_device *dev, char **buf, size_t *off
 	(*count)++;
 
 	if (level == 0) {
-		sprintf(tmp, EOL ".USB dev %d: Bus %d Device %d ID: %04x:%04x",
+		snprintf(tmp, sizeof(tmp), EOL ".USB dev %d: Bus %d Device %d ID: %04x:%04x",
 				(int)(*count), (int)bus_number, (int)device_address,
 				desc.idVendor, desc.idProduct);
 	} else {
-		sprintf(tmp, EOL ".USB dev %d: Bus %d Device %d Device Descriptor:" EOL "\tLength: %d" EOL
+		snprintf(tmp, sizeof(tmp), EOL ".USB dev %d: Bus %d Device %d Device Descriptor:" EOL "\tLength: %d" EOL
 			"\tDescriptor Type: %s" EOL "\tUSB: %04x" EOL "\tDeviceClass: %d" EOL
 			"\tDeviceSubClass: %d" EOL "\tDeviceProtocol: %d" EOL "\tMaxPacketSize0: %d" EOL
 			"\tidVendor: %04x" EOL "\tidProduct: %04x" EOL "\tDeviceRelease: %x" EOL
@@ -795,28 +795,28 @@ static void usb_full(ssize_t *count, libusb_device *dev, char **buf, size_t *off
 
 	err = libusb_open(dev, &handle);
 	if (err) {
-		sprintf(tmp, EOL "  ** dev %d: Failed to open, err %d", (int)(*count), err);
+		snprintf(tmp, sizeof(tmp), EOL "  ** dev %d: Failed to open, err %d", (int)(*count), err);
 		append(buf, tmp, off, len);
 		return;
 	}
 
 	err = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, man, STRBUFLEN);
 	if (err < 0)
-		sprintf((char *)man, "** err(%d)%s", err, usberrstr(err));
+		snprintf((char *)man, sizeof(man), "** err(%d)%s", err, usberrstr(err));
 
 	err = libusb_get_string_descriptor_ascii(handle, desc.iProduct, prod, STRBUFLEN);
 	if (err < 0)
-		sprintf((char *)prod, "** err(%d)%s", err, usberrstr(err));
+		snprintf((char *)prod, sizeof(prod), "** err(%d)%s", err, usberrstr(err));
 
 	if (level == 0) {
 		libusb_close(handle);
-		sprintf(tmp, EOL "  Manufacturer: '%s'" EOL "  Product: '%s'", man, prod);
+		snprintf(tmp, sizeof(tmp), EOL "  Manufacturer: '%s'" EOL "  Product: '%s'", man, prod);
 		append(buf, tmp, off, len);
 		return;
 	}
 
 	if (libusb_kernel_driver_active(handle, 0) == 1) {
-		sprintf(tmp, EOL "   * dev %d: kernel attached", (int)(*count));
+		snprintf(tmp, sizeof(tmp), EOL "   * dev %d: kernel attached", (int)(*count));
 		append(buf, tmp, off, len);
 	}
 
@@ -825,14 +825,14 @@ static void usb_full(ssize_t *count, libusb_device *dev, char **buf, size_t *off
 		if (!setgetdes(*count, dev, handle, &config, 1, buf, off, len)
 		&&  !setgetdes(*count, dev, handle, &config, 0, buf, off, len)) {
 			libusb_close(handle);
-			sprintf(tmp, EOL "  ** dev %d: Failed to set config descriptor to %d or %d",
+			snprintf(tmp, sizeof(tmp), EOL "  ** dev %d: Failed to set config descriptor to %d or %d",
 					(int)(*count), 1, 0);
 			append(buf, tmp, off, len);
 			return;
 		}
 	}
 
-	sprintf(tmp, EOL "     dev %d: Active Config:" EOL "\tDescriptorType: %s" EOL
+	snprintf(tmp, sizeof(tmp), EOL "     dev %d: Active Config:" EOL "\tDescriptorType: %s" EOL
 			"\tNumInterfaces: %d" EOL "\tConfigurationValue: %d" EOL
 			"\tAttributes: %d" EOL "\tMaxPower: %d",
 				(int)(*count), destype(config->bDescriptorType),
@@ -844,7 +844,7 @@ static void usb_full(ssize_t *count, libusb_device *dev, char **buf, size_t *off
 		for (j = 0; j < config->interface[i].num_altsetting; j++) {
 			idesc = &(config->interface[i].altsetting[j]);
 
-			sprintf(tmp, EOL "     _dev %d: Interface Descriptor %d:" EOL
+			snprintf(tmp, sizeof(tmp), EOL "     _dev %d: Interface Descriptor %d:" EOL
 					"\tDescriptorType: %s" EOL "\tInterfaceNumber: %d" EOL
 					"\tNumEndpoints: %d" EOL "\tInterfaceClass: %d" EOL
 					"\tInterfaceSubClass: %d" EOL "\tInterfaceProtocol: %d",
@@ -859,7 +859,7 @@ static void usb_full(ssize_t *count, libusb_device *dev, char **buf, size_t *off
 			for (k = 0; k < (int)(idesc->bNumEndpoints); k++) {
 				epdesc = &(idesc->endpoint[k]);
 
-				sprintf(tmp, EOL "     __dev %d: Interface %d Endpoint %d:" EOL
+				snprintf(tmp, sizeof(tmp), EOL "     __dev %d: Interface %d Endpoint %d:" EOL
 						"\tDescriptorType: %s" EOL
 						"\tEndpointAddress: %s0x%x" EOL
 						"\tAttributes: %s" EOL "\tMaxPacketSize: %d" EOL
@@ -882,9 +882,9 @@ static void usb_full(ssize_t *count, libusb_device *dev, char **buf, size_t *off
 
 	err = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, ser, STRBUFLEN);
 	if (err < 0)
-		sprintf((char *)ser, "** err(%d)%s", err, usberrstr(err));
+		snprintf((char *)ser, sizeof(ser), "** err(%d)%s", err, usberrstr(err));
 
-	sprintf(tmp, EOL "     dev %d: More Info:" EOL "\tManufacturer: '%s'" EOL
+	snprintf(tmp, sizeof(tmp), EOL "     dev %d: More Info:" EOL "\tManufacturer: '%s'" EOL
 			"\tProduct: '%s'" EOL "\tSerial '%s'",
 				(int)(*count), man, prod, ser);
 	append(buf, tmp, off, len);
@@ -1491,13 +1491,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
 	cgpu->usbinfo.bus_number = libusb_get_bus_number(dev);
 	cgpu->usbinfo.device_address = libusb_get_device_address(dev);
 
-	sprintf(devpath, "%d:%d",
+	snprintf(devpath, sizeof(devpath), "%d:%d",
 		(int)(cgpu->usbinfo.bus_number),
 		(int)(cgpu->usbinfo.device_address));
 
 	cgpu->device_path = strdup(devpath);
 
-	sprintf(devstr, "- %s device %s", found->name, devpath);
+	snprintf(devstr, sizeof(devstr), "- %s device %s", found->name, devpath);
 
 	cgusb = calloc(1, sizeof(*cgusb));
 	if (unlikely(!cgusb))
@@ -3308,7 +3308,7 @@ static bool resource_lock(const char *dname, uint8_t bus_number, uint8_t device_
 	if (is_in_use_bd(bus_number, device_address))
 		return false;
 
-	sprintf(name, "cg-usb-%d-%d", (int)bus_number, (int)device_address);
+	snprintf(name, sizeof(name), "cg-usb-%d-%d", (int)bus_number, (int)device_address);
 
 	sec = mksec(dname, bus_number, device_address);
 	if (!sec)
@@ -3384,7 +3384,7 @@ fail:
 	if (is_in_use_bd(bus_number, device_address))
 		return false;
 
-	sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
+	snprintf(name, sizeof(name), "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
 	fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
 	if (fd == -1) {
 		applog(LOG_ERR,
@@ -3484,7 +3484,7 @@ static void resource_unlock(const char *dname, uint8_t bus_number, uint8_t devic
 	HANDLE usbMutex = NULL;
 	char name[64];
 
-	sprintf(name, "cg-usb-%d-%d", (int)bus_number, (int)device_address);
+	snprintf(name, sizeof(name), "cg-usb-%d-%d", (int)bus_number, (int)device_address);
 
 	in_use_get_ress(bus_number, device_address, (void **)(&usbMutex), (void **)(&sec));
 
@@ -3509,7 +3509,7 @@ fila:
 	key_t *key = NULL;
 	int *sem = NULL;
 
-	sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
+	snprintf(name, sizeof(name), "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
 
 	in_use_get_ress(bus_number, device_address, (void **)(&key), (void **)(&sem));