Skip to content

Commit a48275f

Browse files
authored
Merge pull request #5 from nathanmarlor/pr/firmware-bug-fixes
fix: firmware bug fixes (memory, OTA, math.h, stratum)
2 parents 20be927 + 38d2f60 commit a48275f

File tree

10 files changed

+212
-60
lines changed

10 files changed

+212
-60
lines changed

components/asic/bm1370.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ static void _send_BM1370(uint8_t header, uint8_t * data, uint8_t data_len, bool
108108

109109
// allocate memory for buffer
110110
unsigned char * buf = malloc(total_length);
111+
if (buf == NULL) {
112+
ESP_LOGE(TAG, "_send_BM1370: malloc failed");
113+
return;
114+
}
111115

112116
// add the preamble
113117
buf[0] = 0x55;
@@ -142,6 +146,10 @@ static void _send_BM1370(uint8_t header, uint8_t * data, uint8_t data_len, bool
142146
static void _send_simple(uint8_t * data, uint8_t total_length)
143147
{
144148
unsigned char * buf = malloc(total_length);
149+
if (buf == NULL) {
150+
ESP_LOGE(TAG, "_send_simple: malloc failed");
151+
return;
152+
}
145153
memcpy(buf, data, total_length);
146154
SERIAL_send(buf, total_length, BM1370_SERIALTX_DEBUG);
147155

@@ -457,6 +465,10 @@ void BM1370_send_work(void * pvParameters, bm_job * next_bm_job)
457465
memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32);
458466
memcpy(&job.version, &next_bm_job->version, 4);
459467

468+
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
469+
GLOBAL_STATE->valid_jobs[job.job_id] = 0;
470+
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
471+
460472
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) {
461473
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
462474
}
@@ -487,6 +499,10 @@ task_result * BM1370_process_work(void * pvParameters)
487499

488500
// Check if this is a register response (not a job response)
489501
if (!asic_result.is_job_response) {
502+
if (asic_result.cmd.register_address >= sizeof(REGISTER_MAP) / sizeof(REGISTER_MAP[0])) {
503+
ESP_LOGW(TAG, "Register address out of bounds: %02x", asic_result.cmd.register_address);
504+
return NULL;
505+
}
490506
result.register_type = REGISTER_MAP[asic_result.cmd.register_address];
491507
if (result.register_type == REGISTER_INVALID) {
492508
ESP_LOGW(TAG, "Unknown register read: %02x", asic_result.cmd.register_address);

components/stratum/stratum_api.c

Lines changed: 86 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
8585
json_rpc_buffer=0;
8686
}
8787
return 0;
88+
} else if (nbytes == 0) {
89+
// Pool closed the connection gracefully
90+
ESP_LOGI(TAG, "Connection closed by remote host");
91+
if (json_rpc_buffer) {
92+
memset(json_rpc_buffer, 0, json_rpc_buffer_size);
93+
}
94+
return 0;
8895
}
8996

9097
realloc_json_buffer(nbytes);
@@ -96,14 +103,23 @@ char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
96103
line = strdup(tok);
97104
int len = strlen(line);
98105
if (buflen > len + 1)
99-
memmove(json_rpc_buffer, json_rpc_buffer + len + 1, buflen - len + 1);
106+
{
107+
size_t remaining = buflen - len - 1;
108+
memmove(json_rpc_buffer, json_rpc_buffer + len + 1, remaining);
109+
json_rpc_buffer[remaining] = '\0';
110+
}
100111
else
101112
strcpy(json_rpc_buffer, "");
102113
return line;
103114
}
104115

105116
void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
106117
{
118+
if (message->error_str) {
119+
free(message->error_str);
120+
message->error_str = NULL;
121+
}
122+
107123
cJSON * json = cJSON_Parse(stratum_json);
108124

109125
cJSON * id_json = cJSON_GetObjectItem(json, "id");
@@ -145,21 +161,22 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
145161
// if it's an error, then it's a fail
146162
} else if (!cJSON_IsNull(error_json)) {
147163
message->response_success = false;
148-
message->error_str = strdup("unknown");
149164
if (parsed_id < 5) {
150165
result = STRATUM_RESULT_SETUP;
151166
} else {
152167
result = STRATUM_RESULT;
153168
}
169+
const char *err_str = "unknown";
154170
if (cJSON_IsArray(error_json)) {
155171
int len = cJSON_GetArraySize(error_json);
156172
if (len >= 2) {
157173
cJSON * error_msg = cJSON_GetArrayItem(error_json, 1);
158174
if (cJSON_IsString(error_msg)) {
159-
message->error_str = strdup(cJSON_GetStringValue(error_msg));
175+
err_str = cJSON_GetStringValue(error_msg);
160176
}
161177
}
162178
}
179+
message->error_str = strdup(err_str);
163180

164181
// if the result is a boolean, then parse it
165182
} else if (cJSON_IsBool(result_json)) {
@@ -172,10 +189,11 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
172189
message->response_success = true;
173190
} else {
174191
message->response_success = false;
175-
message->error_str = strdup("unknown");
192+
const char *reject_str = "unknown";
176193
if (cJSON_IsString(reject_reason_json)) {
177-
message->error_str = strdup(cJSON_GetStringValue(reject_reason_json));
178-
}
194+
reject_str = cJSON_GetStringValue(reject_reason_json);
195+
}
196+
message->error_str = strdup(reject_str);
179197
}
180198

181199
//if the id is STRATUM_ID_SUBSCRIBE parse it
@@ -224,45 +242,70 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
224242

225243
if (message->method == MINING_NOTIFY) {
226244

227-
mining_notify * new_work = malloc(sizeof(mining_notify));
228-
// new_work->difficulty = difficulty;
229245
cJSON * params = cJSON_GetObjectItem(json, "params");
230-
new_work->job_id = strdup(cJSON_GetArrayItem(params, 0)->valuestring);
231-
new_work->prev_block_hash = strdup(cJSON_GetArrayItem(params, 1)->valuestring);
232-
new_work->coinbase_1 = strdup(cJSON_GetArrayItem(params, 2)->valuestring);
233-
new_work->coinbase_2 = strdup(cJSON_GetArrayItem(params, 3)->valuestring);
246+
cJSON *p0 = params ? cJSON_GetArrayItem(params, 0) : NULL;
247+
cJSON *p1 = params ? cJSON_GetArrayItem(params, 1) : NULL;
248+
cJSON *p2 = params ? cJSON_GetArrayItem(params, 2) : NULL;
249+
cJSON *p3 = params ? cJSON_GetArrayItem(params, 3) : NULL;
250+
cJSON *p4 = params ? cJSON_GetArrayItem(params, 4) : NULL;
251+
cJSON *p5 = params ? cJSON_GetArrayItem(params, 5) : NULL;
252+
cJSON *p6 = params ? cJSON_GetArrayItem(params, 6) : NULL;
253+
cJSON *p7 = params ? cJSON_GetArrayItem(params, 7) : NULL;
254+
if (!p0 || !p1 || !p2 || !p3 || !p4 || !p5 || !p6 || !p7) {
255+
ESP_LOGE(TAG, "MINING_NOTIFY: malformed params: %s", stratum_json);
256+
goto done;
257+
}
258+
259+
mining_notify * new_work = malloc(sizeof(mining_notify));
260+
new_work->job_id = strdup(p0->valuestring);
261+
new_work->prev_block_hash = strdup(p1->valuestring);
262+
new_work->coinbase_1 = strdup(p2->valuestring);
263+
new_work->coinbase_2 = strdup(p3->valuestring);
234264

235-
cJSON * merkle_branch = cJSON_GetArrayItem(params, 4);
236-
new_work->n_merkle_branches = cJSON_GetArraySize(merkle_branch);
265+
new_work->n_merkle_branches = cJSON_GetArraySize(p4);
237266
if (new_work->n_merkle_branches > MAX_MERKLE_BRANCHES) {
238-
printf("Too many Merkle branches.\n");
239-
abort();
267+
ESP_LOGE(TAG, "Too many Merkle branches: %d", new_work->n_merkle_branches);
268+
free(new_work->job_id);
269+
free(new_work->prev_block_hash);
270+
free(new_work->coinbase_1);
271+
free(new_work->coinbase_2);
272+
free(new_work);
273+
goto done;
240274
}
241275
new_work->merkle_branches = malloc(HASH_SIZE * new_work->n_merkle_branches);
242276
for (size_t i = 0; i < new_work->n_merkle_branches; i++) {
243-
hex2bin(cJSON_GetArrayItem(merkle_branch, i)->valuestring, new_work->merkle_branches + HASH_SIZE * i, HASH_SIZE);
277+
cJSON *branch = cJSON_GetArrayItem(p4, i);
278+
if (branch) {
279+
hex2bin(branch->valuestring, new_work->merkle_branches + HASH_SIZE * i, HASH_SIZE);
280+
}
244281
}
245282

246-
new_work->version = strtoul(cJSON_GetArrayItem(params, 5)->valuestring, NULL, 16);
247-
new_work->target = strtoul(cJSON_GetArrayItem(params, 6)->valuestring, NULL, 16);
248-
new_work->ntime = strtoul(cJSON_GetArrayItem(params, 7)->valuestring, NULL, 16);
283+
new_work->version = strtoul(p5->valuestring, NULL, 16);
284+
new_work->target = strtoul(p6->valuestring, NULL, 16);
285+
new_work->ntime = strtoul(p7->valuestring, NULL, 16);
249286

250287
message->mining_notification = new_work;
251288

252-
// params can be varible length
289+
// params can be variable length
253290
int paramsLength = cJSON_GetArraySize(params);
254-
int value = cJSON_IsTrue(cJSON_GetArrayItem(params, paramsLength - 1));
255-
message->should_abandon_work = value;
291+
cJSON *lastParam = cJSON_GetArrayItem(params, paramsLength - 1);
292+
message->should_abandon_work = lastParam ? cJSON_IsTrue(lastParam) : false;
256293
} else if (message->method == MINING_SET_DIFFICULTY) {
257294
cJSON * params = cJSON_GetObjectItem(json, "params");
258-
uint32_t difficulty = cJSON_GetArrayItem(params, 0)->valueint;
259-
260-
message->new_difficulty = difficulty;
295+
cJSON * p0 = params ? cJSON_GetArrayItem(params, 0) : NULL;
296+
if (p0 == NULL) {
297+
ESP_LOGE(TAG, "MINING_SET_DIFFICULTY: missing params");
298+
goto done;
299+
}
300+
message->new_difficulty = p0->valueint;
261301
} else if (message->method == MINING_SET_VERSION_MASK) {
262-
263302
cJSON * params = cJSON_GetObjectItem(json, "params");
264-
uint32_t version_mask = strtoul(cJSON_GetArrayItem(params, 0)->valuestring, NULL, 16);
265-
message->version_mask = version_mask;
303+
cJSON * p0 = params ? cJSON_GetArrayItem(params, 0) : NULL;
304+
if (p0 == NULL) {
305+
ESP_LOGE(TAG, "MINING_SET_VERSION_MASK: missing params");
306+
goto done;
307+
}
308+
message->version_mask = strtoul(p0->valuestring, NULL, 16);
266309
}
267310
done:
268311
cJSON_Delete(json);
@@ -317,7 +360,7 @@ int STRATUM_V1_subscribe(int socket, int send_uid, char * model)
317360
char subscribe_msg[BUFFER_SIZE];
318361
const esp_app_desc_t *app_desc = esp_app_get_description();
319362
const char *version = app_desc->version;
320-
sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitforge/%s/%s\"]}\n", send_uid, model, version);
363+
snprintf(subscribe_msg, sizeof(subscribe_msg), "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitforge/%s/%s\"]}\n", send_uid, model, version);
321364
debug_stratum_tx(subscribe_msg);
322365

323366
return write(socket, subscribe_msg, strlen(subscribe_msg));
@@ -326,16 +369,26 @@ int STRATUM_V1_subscribe(int socket, int send_uid, char * model)
326369
int STRATUM_V1_suggest_difficulty(int socket, int send_uid, uint32_t difficulty)
327370
{
328371
char difficulty_msg[BUFFER_SIZE];
329-
sprintf(difficulty_msg, "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n", send_uid, difficulty);
372+
snprintf(difficulty_msg, sizeof(difficulty_msg), "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n", send_uid, difficulty);
330373
debug_stratum_tx(difficulty_msg);
331374

332375
return write(socket, difficulty_msg, strlen(difficulty_msg));
333376
}
334377

378+
int STRATUM_V1_extranonce_subscribe(int socket, int send_uid)
379+
{
380+
char msg[BUFFER_SIZE];
381+
snprintf(msg, sizeof(msg), "{\"id\": %d, \"method\": \"mining.extranonce.subscribe\", \"params\": []}\n", send_uid);
382+
debug_stratum_tx(msg);
383+
384+
return write(socket, msg, strlen(msg));
385+
}
386+
387+
335388
int STRATUM_V1_authenticate(int socket, int send_uid, const char * username, const char * pass)
336389
{
337390
char authorize_msg[BUFFER_SIZE];
338-
sprintf(authorize_msg, "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n", send_uid, username,
391+
snprintf(authorize_msg, sizeof(authorize_msg), "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n", send_uid, username,
339392
pass);
340393
debug_stratum_tx(authorize_msg);
341394

@@ -353,7 +406,7 @@ int STRATUM_V1_submit_share(int socket, int send_uid, const char * username, con
353406
const uint32_t nonce, const uint32_t version)
354407
{
355408
char submit_msg[BUFFER_SIZE];
356-
sprintf(submit_msg,
409+
snprintf(submit_msg, sizeof(submit_msg),
357410
"{\"id\": %d, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%08lx\", \"%08lx\", \"%08lx\"]}\n",
358411
send_uid, username, jobid, extranonce_2, ntime, nonce, version);
359412
debug_stratum_tx(submit_msg);

components/stratum/utils.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "utils.h"
22

3+
#include <math.h>
34
#include <string.h>
45
#include <stdio.h>
56

main/http_server/axe-os/src/app/components/settings/settings.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export class SettingsComponent {
6464
Validators.required,
6565
Validators.pattern(/^[^:]*$/),
6666
Validators.min(0),
67-
Validators.max(65353)
67+
Validators.max(65535)
6868
]],
6969
stratumUser: [info.stratumUser, [Validators.required]],
7070
stratumPassword: ['*****', [Validators.required]],

0 commit comments

Comments
 (0)