h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit ef087c3849cfbe58f4f77e09367d6fbf152e5498
parent 37a48208d419a6c2797f5705ba37d7b362fcb8fe
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sat, 12 Oct 2024 17:06:50 +0200

Make writemoves (and solver) safer by checking buffer size

Diffstat:
Msrc/core/io_moves.h | 27+++++++++++++++++++++------
Msrc/core/io_trans.h | 8++++----
Msrc/nissy.c | 3---
Msrc/solvers/h48/solve.h | 22+++++++++++++++++++---
Msrc/solvers/h48/solve_multithread.h | 23+++++++++++++++++++----
Mtest/032_invertmoves/invertmoves_tests.c | 4++--
Mtest/061_inverse_trans/inverse_trans_tests.c | 2+-
7 files changed, 66 insertions(+), 23 deletions(-)

diff --git a/src/core/io_moves.h b/src/core/io_moves.h @@ -1,6 +1,6 @@ STATIC uint8_t readmove(char); STATIC uint8_t readmodifier(char); -STATIC int writemoves(uint8_t *, int, char *); +STATIC int64_t writemoves(uint8_t *, int, uint64_t, char *); STATIC uint8_t readmove(char c) @@ -38,18 +38,29 @@ readmodifier(char c) } } -STATIC int -writemoves(uint8_t *m, int n, char *buf) +STATIC int64_t +writemoves(uint8_t *m, int n, uint64_t buf_size, char *buf) { int i; - size_t len; + uint64_t len; const char *s; char *b; - for (i = 0, b = buf; i < n; i++, b++) { + if (buf_size == 0) { + LOG("Error: cannot write moves to buffer of size 0.\n"); + return NISSY_ERROR_BUFFER_SIZE; + } + + for (i = 0, b = buf; i < n; i++, b++, buf_size--) { s = movestr[m[i]]; len = strlen(s); + if (len >= buf_size) { + LOG("Error: the given buffer is too small for " + "writing the given moves.\n"); + goto writemoves_error; + } memcpy(b, s, len); + buf_size -= len; b += len; *b = ' '; } @@ -58,5 +69,9 @@ writemoves(uint8_t *m, int n, char *buf) b--; /* Remove last space */ *b = '\0'; - return b - buf; + return buf_size; + +writemoves_error: + *buf = '\0'; + return NISSY_ERROR_BUFFER_SIZE; } diff --git a/src/core/io_trans.h b/src/core/io_trans.h @@ -1,8 +1,8 @@ -STATIC uint8_t readtrans(const char *); -STATIC void writetrans(uint8_t, char *); +STATIC uint8_t readtrans(const char [static NISSY_SIZE_TRANSFORMATION]); +STATIC void writetrans(uint8_t, char [static NISSY_SIZE_TRANSFORMATION]); STATIC uint8_t -readtrans(const char *buf) +readtrans(const char buf[static NISSY_SIZE_TRANSFORMATION]) { uint8_t t; @@ -14,7 +14,7 @@ readtrans(const char *buf) } STATIC void -writetrans(uint8_t t, char *buf) +writetrans(uint8_t t, char buf[static NISSY_SIZE_TRANSFORMATION]) { if (t >= 48) memcpy(buf, "error trans", 11); diff --git a/src/nissy.c b/src/nissy.c @@ -559,9 +559,6 @@ nissy_solve( solve_h48(c, minmoves, maxmoves, maxsols, data_size, data, sols_size, sols); } - } else if (!strcmp(solver, "simple")) { - return solve_simple( - c, minmoves, maxmoves, maxsols, optimal, sols); } else { LOG("solve: unknown solver '%s'\n", solver); return NISSY_ERROR_INVALID_SOLVER; diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h @@ -10,6 +10,7 @@ typedef struct { uint8_t k; const uint32_t *cocsepdata; const uint8_t *h48data; + uint64_t solutions_size; char **nextsol; uint8_t nissbranch; int8_t npremoves; @@ -55,26 +56,40 @@ allowednextmove_h48(uint8_t *moves, uint8_t n, uint32_t h48branch) STATIC void solve_h48_appendsolution(dfsarg_solveh48_t *arg) { - int strl; + int64_t strl; uint8_t invertedpremoves[MAXLEN]; char *solution = *arg->nextsol; - strl = writemoves(arg->moves, arg->nmoves, *arg->nextsol); + strl = writemoves( + arg->moves, arg->nmoves, arg->solutions_size, *arg->nextsol); + + if (strl < 0) + goto solve_h48_appendsolution_error; *arg->nextsol += strl; + arg->solutions_size -= strl; if (arg->npremoves) { **arg->nextsol = ' '; (*arg->nextsol)++; invertmoves(arg->premoves, arg->npremoves, invertedpremoves); - strl = writemoves(invertedpremoves, arg->npremoves, *arg->nextsol); + strl = writemoves(invertedpremoves, + arg->npremoves, arg->solutions_size, *arg->nextsol); + + if (strl < 0) + goto solve_h48_appendsolution_error; *arg->nextsol += strl; + arg->solutions_size -= strl; } LOG("Solution found: %s\n", solution); **arg->nextsol = '\n'; (*arg->nextsol)++; (*arg->nsols)++; + +solve_h48_appendsolution_error: + /* We could add some logging, but writemoves() already does */ + return; } STATIC_INLINE bool @@ -188,6 +203,7 @@ solve_h48( .k = info.bits, .cocsepdata = get_cocsepdata_constptr(data), .h48data = get_h48data_constptr(data), + .solutions_size = solutions_size, .nextsol = &solutions }; diff --git a/src/solvers/h48/solve_multithread.h b/src/solvers/h48/solve_multithread.h @@ -27,12 +27,17 @@ STATIC void solve_h48_appendsolution_thread(dfsarg_solveh48_t *arg, task_queue_t *tq) { pthread_mutex_lock(&tq->mutex); - int strl = 0; + int64_t strl = 0; uint8_t invertedpremoves[MAXLEN]; char *solution = *arg->nextsol; - strl = writemoves(arg->moves, arg->nmoves, *arg->nextsol); + strl = writemoves( + arg->moves, arg->nmoves, arg->solutions_size, *arg->nextsol); + + if (strl < 0) + goto solve_h48_appendsolution_thread_error; *arg->nextsol += strl; + arg->solutions_size -= strl; if (arg->npremoves) { @@ -40,14 +45,22 @@ solve_h48_appendsolution_thread(dfsarg_solveh48_t *arg, task_queue_t *tq) (*arg->nextsol)++; invertmoves(arg->premoves, arg->npremoves, invertedpremoves); - strl = writemoves(invertedpremoves, arg->npremoves, *arg->nextsol); + strl = writemoves(invertedpremoves, + arg->npremoves, arg->solutions_size, *arg->nextsol); + + if (strl < 0) + goto solve_h48_appendsolution_thread_error; *arg->nextsol += strl; + arg->solutions_size -= strl; } LOG("Solution found: %s\n", solution); **arg->nextsol = '\n'; (*arg->nextsol)++; (*arg->nsols)++; + +solve_h48_appendsolution_thread_error: + /* We could add some logging, but writemoves() already does */ pthread_mutex_unlock(&tq->mutex); } @@ -264,7 +277,9 @@ solve_h48_multithread( .k = info.bits, .cocsepdata = get_cocsepdata_constptr(data), .h48data = get_h48data_constptr(data), - .nextsol = &solutions}; + .solutions_size = solutions_size, + .nextsol = &solutions + }; task_queue_t q; init_queue(&q); diff --git a/test/032_invertmoves/invertmoves_tests.c b/test/032_invertmoves/invertmoves_tests.c @@ -3,7 +3,7 @@ #define MAXMOVES 20 int64_t readmoves(const char *, int, uint8_t *); -void writemoves(uint8_t *, int, char *); +void writemoves(uint8_t *, int, uint64_t, char *); void invertmoves(uint8_t *, uint8_t, uint8_t *); void run(void) { @@ -15,7 +15,7 @@ void run(void) { c = readmoves(movestr, MAXMOVES, moves); invertmoves(moves, c, ret); - writemoves(ret, c, outstr); + writemoves(ret, c, STRLENMAX, outstr); printf("%s\n", outstr); } diff --git a/test/061_inverse_trans/inverse_trans_tests.c b/test/061_inverse_trans/inverse_trans_tests.c @@ -1,6 +1,6 @@ #include "../test.h" -uint8_t readtrans(char *); +uint8_t readtrans(char [static NISSY_SIZE_TRANSFORMATION]); uint8_t inverse_trans(uint8_t); cube_t applymoves(cube_t, char *); cube_t applytrans(cube_t, char *);