From 46b6b07afa05c0a9c39e98f7bb856b70530bf445 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 12 Aug 2013 16:02:20 +1000 Subject: [PATCH] Avoid a potential overflow should a pool specify a large nonce2 length with stratum. --- cgminer.c | 17 +++++++++++++---- util.c | 12 +++++++++--- util.h | 1 + 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/cgminer.c b/cgminer.c index d2d59655..891fc2cf 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5587,16 +5587,17 @@ void set_target(unsigned char *dest_target, double diff) static void gen_stratum_work(struct pool *pool, struct work *work) { unsigned char merkle_root[32], merkle_sha[64]; + uint32_t *data32, *swap32, nonce2; char *header, *merkle_hash; - uint32_t *data32, *swap32; + size_t nonce2_len; int i; cg_wlock(&pool->data_lock); /* Update coinbase */ - memcpy(pool->coinbase + pool->nonce2_offset, &pool->nonce2, pool->n2size); - work->nonce2 = bin2hex((const unsigned char *)&pool->nonce2, pool->n2size); - pool->nonce2++; + memcpy(pool->coinbase + pool->nonce2_offset, &pool->nonce2, sizeof(uint32_t)); + nonce2 = pool->nonce2++; + nonce2_len = pool->n2size; /* Downgrade to a read lock to read off the pool variables */ cg_dwlock(&pool->data_lock); @@ -5637,6 +5638,14 @@ static void gen_stratum_work(struct pool *pool, struct work *work) work->ntime = strdup(pool->swork.ntime); cg_runlock(&pool->data_lock); + /* nonce2 length can be bigger than uint32_t but we only use the 4 + * bytes so avoid potential overflow if a pool has set a large length */ + align_len(&nonce2_len); + work->nonce2 = calloc(nonce2_len, 1); + if (unlikely(!work->nonce2)) + quit(1, "Failed to calloc work nonce2 in gen_stratum_work"); + __bin2hex(work->nonce2, (const unsigned char *)&nonce2, sizeof(uint32_t)); + applog(LOG_DEBUG, "Generated stratum merkle %s", merkle_hash); applog(LOG_DEBUG, "Generated stratum header %s", header); applog(LOG_DEBUG, "Work job_id %s nonce2 %s ntime %s", work->job_id, work->nonce2, work->ntime); diff --git a/util.c b/util.c index cd813e46..f42515b0 100644 --- a/util.c +++ b/util.c @@ -576,12 +576,19 @@ char *get_proxy(char *url, struct pool *pool) return url; } +void __bin2hex(char *s, const unsigned char *p, size_t len) +{ + int i; + + for (i = 0; i < (int)len; i++) + sprintf(s + (i * 2), "%02x", (unsigned int)p[i]); +} + /* Returns a malloced array string of a binary value of arbitrary length. The * array is rounded up to a 4 byte size to appease architectures that need * aligned array sizes */ char *bin2hex(const unsigned char *p, size_t len) { - unsigned int i; ssize_t slen; char *s; @@ -592,8 +599,7 @@ char *bin2hex(const unsigned char *p, size_t len) if (unlikely(!s)) quithere(1, "Failed to calloc"); - for (i = 0; i < len; i++) - sprintf(s + (i * 2), "%02x", (unsigned int) p[i]); + __bin2hex(s, p, len); return s; } diff --git a/util.h b/util.h index dd179319..dc92c443 100644 --- a/util.h +++ b/util.h @@ -70,6 +70,7 @@ enum dev_reason; struct cgpu_info; int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg); void thr_info_cancel(struct thr_info *thr); +void __bin2hex(char *s, const unsigned char *p, size_t len); void nmsleep(unsigned int msecs); void nusleep(unsigned int usecs); void cgtime(struct timeval *tv);