From e3765b81fc2ce80614afb358f429414c85c01669 Mon Sep 17 00:00:00 2001 From: Kagami Hiiragi Date: Sun, 11 Jan 2015 05:59:32 +0300 Subject: [PATCH] Better input validation --- lib/platform.js | 8 ++++---- src/pow.cc | 37 ++++++++++++++++--------------------- src/pow.h | 3 +++ src/worker.cc | 28 +++++++++++++++++++--------- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/lib/platform.js b/lib/platform.js index 3a7fc3d..c8b47f8 100644 --- a/lib/platform.js +++ b/lib/platform.js @@ -56,14 +56,14 @@ exports.pow = function(opts) { // Check all input params prematurely to not let promise executor or // worker to fail because of it. - // 1 - UINT32_MAX - assert(poolSize > 0, "Pool size is too low"); - assert(poolSize <= 4294967295, "Pool size is too high"); - // 0 - (2^53 - 1) + assert(typeof poolSize === "number", "Bad pool size"); + assert(poolSize >= 1, "Pool size is too low"); + assert(poolSize <= 1024, "Pool size is too high"); assert(typeof opts.target === "number", "Bad target"); assert(opts.target >= 0, "Target is too low"); assert(opts.target <= 9007199254740991, "Target is too high"); assert(Buffer.isBuffer(opts.initialHash), "Bad initial hash"); + assert(opts.initialHash.length === 64, "Bad initial hash"); // TODO(Kagami): Allow to cancel a POW (see `platform.browser.js`). return new promise(function(resolve, reject) { diff --git a/src/pow.cc b/src/pow.cc index aa78c15..9da2f8e 100644 --- a/src/pow.cc +++ b/src/pow.cc @@ -9,15 +9,15 @@ #include #include #include +#include "./pow.h" -#define HASH_SIZE 64 - -typedef enum { - RESULT_NOT_READY, - RESULT_OK, - RESULT_OVERFLOW, - RESULT_ERROR -} Result; +enum PowResult { + RESULT_OK = 0, + RESULT_OVERFLOW = -1, + RESULT_ERROR = -2, + RESULT_BAD_INPUT = -3, + RESULT_NOT_READY = -4 +}; // Global arguments. size_t g_pool_size; @@ -27,7 +27,7 @@ uint64_t g_max_nonce; // Shared variables for threads. pthread_mutex_t g_mutex; -Result g_result = RESULT_NOT_READY; +PowResult g_result = RESULT_NOT_READY; uint64_t g_nonce; inline uint64_t ntohll(uint64_t x) { @@ -38,7 +38,7 @@ inline uint64_t ntohll(uint64_t x) { } // Set POW computation result in a thread-safe way. -void set_result(Result res, uint64_t nonce) { +void set_result(PowResult res, uint64_t nonce) { pthread_mutex_lock(&g_mutex); if (g_result == RESULT_NOT_READY) { g_result = res; @@ -87,6 +87,9 @@ int pow(size_t pool_size, const uint8_t* initial_hash, uint64_t max_nonce, uint64_t* nonce) { + if (pool_size < 1 || pool_size > MAX_POOL_SIZE) { + return RESULT_BAD_INPUT; + } g_pool_size = pool_size; g_target = target; g_initial_hash = (uint8_t *)initial_hash; @@ -112,18 +115,10 @@ int pow(size_t pool_size, pthread_join(threads[i], NULL); } - switch (g_result) { - case RESULT_OK: - *nonce = g_nonce; - error = 0; - break; - case RESULT_OVERFLOW: - error = -1; - break; - default: - error = -2; + if (g_result == RESULT_OK) { + *nonce = g_nonce; } pthread_mutex_destroy(&g_mutex); - return error; + return g_result; } diff --git a/src/pow.h b/src/pow.h index e4cce93..28bc894 100644 --- a/src/pow.h +++ b/src/pow.h @@ -1,6 +1,9 @@ #ifndef BITMESSAGE_POW_H #define BITMESSAGE_POW_H +#define MAX_POOL_SIZE 1024 +#define HASH_SIZE 64 + int pow(size_t pool_size, uint64_t target, const uint8_t* initial_hash, diff --git a/src/worker.cc b/src/worker.cc index 3116a2d..c265505 100644 --- a/src/worker.cc +++ b/src/worker.cc @@ -68,22 +68,32 @@ class PowWorker : public NanAsyncWorker { NAN_METHOD(PowAsync) { NanScope(); - NanCallback *callback = new NanCallback(args[3].As()); + if (args.Length() != 4 || + !args[0]->IsNumber() || // pool_size + !args[1]->IsNumber() || // target + !args[2]->IsObject() || // initial_hash + !args[3]->IsFunction()) { // cb + NanThrowError("Bad input"); + NanReturnUndefined(); + } + size_t pool_size = args[0]->Uint32Value(); uint64_t target = args[1]->IntegerValue(); size_t length = Buffer::Length(args[2]->ToObject()); - char* buf = Buffer::Data(args[2]->ToObject()); + if (pool_size < 1 || pool_size > MAX_POOL_SIZE || length != HASH_SIZE) { + NanThrowError("Bad input"); + NanReturnUndefined(); + } uint8_t* initial_hash = (uint8_t *)malloc(length); - if (initial_hash == NULL) { - Local argv[] = {NanError("Internal error")}; - callback->Call(1, argv); - } else { - memcpy(initial_hash, buf, length); - NanAsyncQueueWorker( - new PowWorker(callback, pool_size, target, initial_hash)); + NanThrowError("Internal error"); + NanReturnUndefined(); } + char* buf = Buffer::Data(args[2]->ToObject()); + memcpy(initial_hash, buf, length); + NanCallback* callback = new NanCallback(args[3].As()); + NanAsyncQueueWorker(new PowWorker(callback, pool_size, target, initial_hash)); NanReturnUndefined(); }