commit da8fdd4955fd24666643915a6728678e9965a0d3
parent 14689e29252e608d51c5b52e61e43471d2aa021e
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Sat, 12 Oct 2024 11:11:28 +0200
Make writecube safer
Diffstat:
18 files changed, 130 insertions(+), 111 deletions(-)
diff --git a/src/core/io_cube.h b/src/core/io_cube.h
@@ -1,5 +1,5 @@
STATIC cube_t readcube(const char *, const char *);
-STATIC int writecube(const char *, cube_t, char *);
+STATIC int64_t writecube(const char *, cube_t, uint64_t, char *);
STATIC void log_available_formats(void);
STATIC uint8_t readco(const char *);
STATIC uint8_t readcp(const char *);
@@ -10,10 +10,10 @@ STATIC cube_t readcube_H48(const char *);
STATIC uint8_t readpiece_LST(const char **);
STATIC cube_t readcube_LST(const char *);
-STATIC int writepiece_LST(uint8_t, char *);
-STATIC void writecube_B32(cube_t, char *);
-STATIC void writecube_H48(cube_t, char *);
-STATIC void writecube_LST(cube_t, char *);
+STATIC int64_t writepiece_LST(uint8_t, uint64_t, char *);
+STATIC int64_t writecube_B32(cube_t, uint64_t, char *);
+STATIC int64_t writecube_H48(cube_t, uint64_t, char *);
+STATIC int64_t writecube_LST(cube_t, uint64_t, char *);
STATIC uint8_t b32toedge(char);
STATIC uint8_t b32tocorner(char);
@@ -23,7 +23,7 @@ STATIC char cornertob32(uint8_t);
STATIC struct {
const char *name;
cube_t (*read)(const char *);
- void (*write)(cube_t, char *);
+ int64_t (*write)(cube_t, uint64_t, char *);
} ioformat[] =
{
{ .name = "B32", .read = readcube_B32, .write = writecube_B32 },
@@ -46,35 +46,18 @@ readcube(const char *format, const char *buf)
return ZERO_CUBE;
}
-STATIC int
-writecube(const char *format, cube_t cube, char *buf)
+STATIC int64_t
+writecube(const char *format, cube_t cube, uint64_t buf_size, char *buf)
{
- char *errormsg;
- size_t len;
-
- if (!isconsistent(cube)) {
- errormsg = "ERROR: inconsistent";
- goto writecube_error;
- }
-
int i;
- for (i = 0; ioformat[i].write != NULL; i++) {
- if (!strcmp(format, ioformat[i].name)) {
- ioformat[i].write(cube, buf);
- return 0;
- }
- }
+ for (i = 0; ioformat[i].write != NULL; i++)
+ if (!strcmp(format, ioformat[i].name))
+ return ioformat[i].write(cube, buf_size, buf);
LOG("Cannot write cube: unknown format '%s'\n", format);
log_available_formats();
- errormsg = "ERROR: format";
-
-writecube_error:
- len = strlen(errormsg);
- memcpy(buf, errormsg, len);
- buf[len] = '\0';
- return 1;
+ return NISSY_ERROR_INVALID_FORMAT;
}
STATIC void
@@ -249,11 +232,14 @@ readcube_LST(const char *buf)
return cubefromarray(c, e);
}
-STATIC int
-writepiece_LST(uint8_t piece, char *buf)
+STATIC int64_t
+writepiece_LST(uint8_t piece, uint64_t buf_size, char *buf)
{
char digits[3];
- int i, len;
+ uint64_t i, len;
+
+ if (piece > 99 || buf_size < 3)
+ return 0;
len = 0;
while (piece != 0) {
@@ -261,6 +247,9 @@ writepiece_LST(uint8_t piece, char *buf)
piece /= 10;
}
+ if (buf_size < len+2)
+ return 0;
+
if (len == 0)
digits[len++] = '0';
@@ -273,12 +262,19 @@ writepiece_LST(uint8_t piece, char *buf)
return len+2;
}
-STATIC void
-writecube_B32(cube_t cube, char *buf)
+STATIC int64_t
+writecube_B32(cube_t cube, uint64_t buf_size, char *buf)
{
int i;
uint8_t corner[8], edge[12];
+ if (buf_size < NISSY_SIZE_B32) {
+ LOG("Cannot write cube in B32 format: buffer size must be "
+ "at least %" PRIu64 " bytes, but the provided one is %"
+ PRIu64 " bytes.\n", NISSY_SIZE_B32, buf_size);
+ return NISSY_ERROR_BUFFER_SIZE;
+ }
+
pieces(&cube, corner, edge);
for (i = 0; i < 8; i++)
@@ -290,14 +286,23 @@ writecube_B32(cube_t cube, char *buf)
buf[i+9] = edgetob32(edge[i]);
buf[21] = '\0';
+
+ return NISSY_OK;
}
-STATIC void
-writecube_H48(cube_t cube, char *buf)
+STATIC int64_t
+writecube_H48(cube_t cube, uint64_t buf_size, char *buf)
{
uint8_t piece, perm, orient, corner[8], edge[12];
int i;
+ if (buf_size < NISSY_SIZE_H48) {
+ LOG("Cannot write cube in H48 format: buffer size must be "
+ "at least %" PRIu64 " bytes, but the provided one is %"
+ PRIu64 " bytes.\n", NISSY_SIZE_H48, buf_size);
+ return NISSY_ERROR_BUFFER_SIZE;
+ }
+
pieces(&cube, corner, edge);
for (i = 0; i < 12; i++) {
@@ -321,13 +326,15 @@ writecube_H48(cube_t cube, char *buf)
}
buf[48+39] = '\0';
+
+ return NISSY_OK;
}
-STATIC void
-writecube_LST(cube_t cube, char *buf)
+STATIC int64_t
+writecube_LST(cube_t cube, uint64_t buf_size, char *buf)
{
int i;
- size_t ptr;
+ uint64_t ptr;
uint8_t piece, corner[8], edge[12];
ptr = 0;
@@ -335,15 +342,27 @@ writecube_LST(cube_t cube, char *buf)
for (i = 0; i < 8; i++) {
piece = corner[i];
- ptr += writepiece_LST(piece, buf + ptr);
+ ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
+ if (ptr == 0)
+ goto writecube_LST_error;
}
for (i = 0; i < 12; i++) {
piece = edge[i];
- ptr += writepiece_LST(piece, buf + ptr);
+ ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
+ if (ptr == 0)
+ goto writecube_LST_error;
}
- *(buf+ptr-2) = 0;
+ *(buf+ptr-2) = '\0';
+
+ return NISSY_OK;
+
+writecube_LST_error:
+ LOG("Cannot write cube in LST: buffer is too small (%" PRIu64
+ " bytes given). The LST format has a variable size, try a "
+ "larger buffer.\n", buf_size);
+ return NISSY_ERROR_BUFFER_SIZE;
}
STATIC uint8_t
diff --git a/src/nissy.c b/src/nissy.c
@@ -5,15 +5,14 @@
#include <stdbool.h>
#include <string.h>
+#include "nissy.h"
#include "utils/utils.h"
#include "arch/arch.h"
#include "core/core.h"
#include "solvers/solvers.h"
-#include "nissy.h"
-
int parse_h48_solver(const char *, uint8_t [static 1], uint8_t [static 1]);
-STATIC int64_t write_result(cube_t, char [static 22]);
+STATIC int64_t write_result(cube_t, char [static NISSY_SIZE_B32]);
STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN],
const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t);
STATIC bool checkdata(const char *, const tableinfo_t *);
@@ -107,9 +106,9 @@ distribution_equal(
}
STATIC int64_t
-write_result(cube_t cube, char result[static 22])
+write_result(cube_t cube, char result[static NISSY_SIZE_B32])
{
- writecube("B32", cube, result);
+ writecube("B32", cube, NISSY_SIZE_B32, result);
if (!issolvable(cube)) {
LOG("Warning: resulting cube is not solvable\n");
@@ -121,9 +120,9 @@ write_result(cube_t cube, char result[static 22])
int64_t
nissy_compose(
- const char cube[static 22],
- const char permutation[static 22],
- char result[static 22]
+ const char cube[static NISSY_SIZE_B32],
+ const char permutation[static NISSY_SIZE_B32],
+ char result[static NISSY_SIZE_B32]
)
{
cube_t c, p, res;
@@ -156,14 +155,14 @@ nissy_compose(
return write_result(res, result);
nissy_compose_error:
- writecube("B32", ZERO_CUBE, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
return err;
}
int64_t
nissy_inverse(
- const char cube[static 22],
- char result[static 22]
+ const char cube[static NISSY_SIZE_B32],
+ char result[static NISSY_SIZE_B32]
)
{
cube_t c, res;
@@ -188,15 +187,15 @@ nissy_inverse(
return write_result(res, result);
nissy_inverse_error:
- writecube("B32", ZERO_CUBE, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
return err;
}
int64_t
nissy_applymoves(
- const char cube[static 22],
+ const char cube[static NISSY_SIZE_B32],
const char *moves,
- char result[static 22]
+ char result[static NISSY_SIZE_B32]
)
{
cube_t c, res;
@@ -227,15 +226,15 @@ nissy_applymoves(
return write_result(res, result);
nissy_applymoves_error:
- writecube("B32", ZERO_CUBE, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
return err;
}
int64_t
nissy_applytrans(
- const char cube[static 22],
- const char transformation[static 12],
- char result[static 22]
+ const char cube[static NISSY_SIZE_B32],
+ const char transformation[static NISSY_SIZE_TRANSFORMATION],
+ char result[static NISSY_SIZE_B32]
)
{
cube_t c, res;
@@ -260,14 +259,14 @@ nissy_applytrans(
return write_result(res, result);
nissy_applytrans_error:
- writecube("B32", ZERO_CUBE, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
return err;
}
int64_t
nissy_frommoves(
const char *moves,
- char result[static 22]
+ char result[static NISSY_SIZE_B32]
)
{
cube_t res;
@@ -290,7 +289,7 @@ nissy_frommoves(
return write_result(res, result);
nissy_frommoves_error:
- writecube("B32", ZERO_CUBE, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
return err;
}
@@ -304,7 +303,6 @@ nissy_convert(
)
{
cube_t c;
- int ret;
int64_t err;
if (format_in == NULL) {
@@ -327,28 +325,15 @@ nissy_convert(
c = readcube(format_in, cube_string);
- if (iserror(c)) {
- err = NISSY_ERROR_INVALID_CUBE;
- goto nissy_convert_error;
- }
-
- ret = writecube(format_out, c, result);
-
- if (ret != 0) {
- /* Assume the format was invalid */
- err = NISSY_ERROR_INVALID_FORMAT;
- goto nissy_convert_error;
- }
-
if (!isconsistent(c)) {
- err = NISSY_ERROR_UNKNOWN;
+ err = NISSY_ERROR_INVALID_CUBE;
goto nissy_convert_error;
}
- return NISSY_OK;
+ return writecube(format_out, c, result_size, result);
nissy_convert_error:
- /* We don't write anything to result, we don't know the format */
+ result[0] = '\0';
return err;
}
@@ -359,7 +344,7 @@ nissy_getcube(
int64_t cp,
int64_t co,
const char *options,
- char result[static 22]
+ char result[static NISSY_SIZE_B32]
)
{
int i;
@@ -498,7 +483,7 @@ nissy_checkdata(
int64_t
nissy_solve(
- const char cube[static 22],
+ const char cube[static NISSY_SIZE_B32],
const char *solver,
uint8_t nissflag,
int8_t minmoves,
@@ -671,6 +656,14 @@ nissy_explainerror(
"is NULL.\n", NISSY_ERROR_NULL_POINTER
);
return NISSY_OK;
+ case NISSY_ERROR_BUFFER_SIZE:
+ write(
+ "The value %" PRId64 " means that one of the buffers "
+ "provided is too small. For example, it could be too "
+ "small to hold the result or too small to hold the data "
+ "generated by gendata.\n", NISSY_ERROR_BUFFER_SIZE
+ );
+ return NISSY_OK;
case NISSY_ERROR_DATA:
write(
"The value %" PRId64 " means that the provided data is "
diff --git a/src/nissy.h b/src/nissy.h
@@ -35,11 +35,17 @@ for example 'rotation UF' or 'mirrored BL'.
#define NISSY_ERROR_INVALID_FORMAT INT64_C(-40)
#define NISSY_ERROR_INVALID_SOLVER INT64_C(-50)
#define NISSY_ERROR_NULL_POINTER INT64_C(-60)
+#define NISSY_ERROR_BUFFER_SIZE INT64_C(-61)
#define NISSY_ERROR_DATA INT64_C(-70)
#define NISSY_ERROR_OPTIONS INT64_C(-80)
#define NISSY_ERROR_INVALID_CODE INT64_C(-90)
#define NISSY_ERROR_UNKNOWN INT64_C(-999)
+/* Some constants for size for I/O buffers */
+#define NISSY_SIZE_B32 UINT64_C(22)
+#define NISSY_SIZE_H48 UINT64_C(88)
+#define NISSY_SIZE_TRANSFORMATION UINT64_C(12)
+
/* Flags for NISS options */
#define NISSY_NISSFLAG_NORMAL UINT8_C(1)
#define NISSY_NISSFLAG_INVERSE UINT8_C(2)
@@ -68,9 +74,9 @@ Return values:
NISSY_ERROR_UNKNOWN - An unknown error occurred.
*/
int64_t nissy_compose(
- const char cube[static 22],
- const char permutation[static 22],
- char result[static 22]
+ const char cube[static NISSY_SIZE_B32],
+ const char permutation[static NISSY_SIZE_B32],
+ char result[static NISSY_SIZE_B32]
);
/*
@@ -89,8 +95,8 @@ Return values:
NISSY_ERROR_UNKNOWN - An unknown error occurred.
*/
int64_t nissy_inverse(
- const char cube[static 22],
- char result[static 22]
+ const char cube[static NISSY_SIZE_B32],
+ char result[static NISSY_SIZE_B32]
);
/*
@@ -111,9 +117,9 @@ Return values:
NISSY_ERROR_NULL_POINTER - The 'moves' argument is NULL.
*/
int64_t nissy_applymoves(
- const char cube[static 22],
+ const char cube[static NISSY_SIZE_B32],
const char *moves,
- char result[static 22]
+ char result[static NISSY_SIZE_B32]
);
/*
@@ -132,9 +138,9 @@ Return values:
NISSY_ERROR_INVALID_TRANS - The given transformation is invalid.
*/
int64_t nissy_applytrans(
- const char cube[static 22],
- const char transformation[static 12],
- char result[static 22]
+ const char cube[static NISSY_SIZE_B32],
+ const char transformation[static NISSY_SIZE_TRANSFORMATION],
+ char result[static NISSY_SIZE_B32]
);
/*
@@ -154,7 +160,7 @@ Return values:
*/
int64_t nissy_frommoves(
const char *moves,
- char result[static 22]
+ char result[static NISSY_SIZE_B32]
);
/*
@@ -169,6 +175,7 @@ Parameters:
Return values:
NISSY_OK - The conversion was performed succesfully.
+ NISSY_ERROR_BUFFER_SIZE - The given buffer is too small for the result.
NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
NISSY_ERROR_INVALID_FORMAT - At least one of the given formats is invalid.
NISSY_ERROR_UNKNOWN - An unknown error occurred.
@@ -208,7 +215,7 @@ int64_t nissy_getcube(
int64_t cp,
int64_t co,
const char *options,
- char result[static 22]
+ char result[static NISSY_SIZE_B32]
);
/*
@@ -313,7 +320,7 @@ Return values:
Any value >= 0 - The number of solutions found.
*/
int64_t nissy_solve(
- const char cube[static 22],
+ const char cube[static NISSY_SIZE_B32],
const char *solver,
uint8_t nissflag,
int8_t minmoves,
diff --git a/test/020_io_H48_read_write/io_H48_tests.c b/test/020_io_H48_read_write/io_H48_tests.c
@@ -16,7 +16,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Cube is not solvable\n");
} else {
- writecube("H48", cube, str);
+ writecube("H48", cube, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/021_io_B32_write/io_B32_read_tests.c b/test/021_io_B32_write/io_B32_read_tests.c
@@ -16,7 +16,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Cube is not solvable\n");
} else {
- writecube("B32", cube, str);
+ writecube("B32", cube, NISSY_SIZE_B32, str);
printf("%s\n", str);
}
}
diff --git a/test/022_io_B32_read/io_B32_read_tests.c b/test/022_io_B32_read/io_B32_read_tests.c
@@ -16,7 +16,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Cube is not solvable\n");
} else {
- writecube("H48", cube, str);
+ writecube("H48", cube, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/023_io_LST_write/io_LST_write_tests.c b/test/023_io_LST_write/io_LST_write_tests.c
@@ -16,7 +16,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Cube is not solvable\n");
} else {
- writecube("LST", cube, str);
+ writecube("LST", cube, STRLENMAX, str);
printf("%s\n", str);
}
}
diff --git a/test/024_io_LST_read/io_LST_read_tests.c b/test/024_io_LST_read/io_LST_read_tests.c
@@ -16,7 +16,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Cube is not solvable\n");
} else {
- writecube("H48", cube, str);
+ writecube("H48", cube, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/030_move/move_tests.c b/test/030_move/move_tests.c
@@ -17,7 +17,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Moved cube is not solvable\n");
} else {
- writecube("H48", cube, cubestr);
+ writecube("H48", cube, NISSY_SIZE_H48, cubestr);
printf("%s\n", cubestr);
}
}
diff --git a/test/031_premove/premove_tests.c b/test/031_premove/premove_tests.c
@@ -21,7 +21,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Moved cube is not solvable\n");
} else {
- writecube("H48", cube, cubestr);
+ writecube("H48", cube, NISSY_SIZE_H48, cubestr);
printf("%s\n", cubestr);
}
}
diff --git a/test/040_inverse_cube/inverse_tests.c b/test/040_inverse_cube/inverse_tests.c
@@ -15,7 +15,7 @@ void run(void) {
} else if (!issolvable(inv)) {
printf("Inverted cube is not solvable\n");
} else {
- writecube("H48", inv, str);
+ writecube("H48", inv, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/050_compose/compose_tests.c b/test/050_compose/compose_tests.c
@@ -18,7 +18,7 @@ void run(void) {
} else if (!issolvable(c3)) {
printf("Composed cube is not solvable\n");
} else {
- writecube("H48", c3, str);
+ writecube("H48", c3, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/060_transform/transform_tests.c b/test/060_transform/transform_tests.c
@@ -17,7 +17,7 @@ void run(void) {
} else if (!issolvable(cube)) {
printf("Transformed cube is not solvable\n");
} else {
- writecube("H48", cube, cubestr);
+ writecube("H48", cube, NISSY_SIZE_H48, cubestr);
printf("%s\n", cubestr);
}
}
diff --git a/test/075_set_eo/set_eo_tests.c b/test/075_set_eo/set_eo_tests.c
@@ -30,7 +30,7 @@ void run(void) {
fprintf(stderr, "\n");
printf("Setting EO resulted in inconsistent cube\n");
} else {
- writecube("H48", cube, str);
+ writecube("H48", cube, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/076_copy_corners/copy_corners_tests.c b/test/076_copy_corners/copy_corners_tests.c
@@ -19,7 +19,7 @@ void run(void) {
} else if (!isconsistent(c1)) {
printf("Setting EO resulted in inconsistent cube\n");
} else {
- writecube("H48", c1, str);
+ writecube("H48", c1, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/077_copy_edges/copy_edges_tests.c b/test/077_copy_edges/copy_edges_tests.c
@@ -19,7 +19,7 @@ void run(void) {
} else if (!isconsistent(c1)) {
printf("Setting EO resulted in inconsistent cube\n");
} else {
- writecube("H48", c1, str);
+ writecube("H48", c1, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/081_getcube/getcube_tests.c b/test/081_getcube/getcube_tests.c
@@ -23,7 +23,7 @@ void run(void) {
} else if (!isconsistent(cube)) {
printf("Inconsistent cube\n");
} else {
- writecube("H48", cube, str);
+ writecube("H48", cube, NISSY_SIZE_H48, str);
printf("%s\n", str);
}
}
diff --git a/test/test.h b/test/test.h
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <string.h>
+#include "../src/nissy.h"
#include "../src/arch/arch.h"
#include "../src/solvers/tables_types_macros.h"
#include "../src/solvers/h48/coordinate_macros.h"
@@ -23,8 +24,7 @@ bool isconsistent(cube_t);
bool issolvable(cube_t);
bool issolved(cube_t);
cube_t readcube(char *, char *);
-void writecube(char *, cube_t, char *);
-void nissy_setlogger(void (*logger_function)(const char *, ...));
+int64_t writecube(char *, cube_t, uint64_t, char *);
/* Test function to be implemented by all tests */
void run(void);