Guard against most egregious mistakes in calling the library

LuaJIT FFI is not inherently memory safe and there is no way
to completely guard against the caller doing something that
will trample over memory, but we can get pretty close. Biggest
issue is that an empty table will stand-in for a ref struct with
a null ref. So check for that in all the calls. In the calls that
raise errors we now have a specific error for it. In the other
functions the "nil" object is handled quietly but without a nullptr
dereference and hopefully no UB.
This commit is contained in:
2024-02-12 22:03:45 -06:00
parent 59bdeedc18
commit e43272487f
8 changed files with 428 additions and 273 deletions

View File

@@ -20,38 +20,39 @@ enum KiwiErrKind {
KiwiErrBadRequiredStrength,
KiwiErrInternalSolverError,
KiwiErrAlloc,
KiwiErrNullObject,
KiwiErrUnknown,
};
enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ };
typedef struct {
void* private_;
} KiwiVarRef;
struct KiwiVarRefType;
struct KiwiConstraintRefType;
typedef struct {
typedef struct KiwiVarRefType* KiwiVarRef;
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
struct KiwiTerm {
KiwiVarRef var;
double coefficient;
} KiwiTerm;
};
typedef struct {
typedef struct KiwiExpression {
double constant;
int term_count;
KiwiTerm terms[1];
} KiwiExpression;
struct KiwiTerm terms[1]; // LuaJIT: struct KiwiTerm terms_[?];
}* KiwiExpressionPtr;
typedef struct {
void* private_;
} KiwiConstraintRef;
typedef const struct KiwiExpression* KiwiExpressionConstPtr;
typedef struct {
typedef struct KiwiErr {
enum KiwiErrKind kind;
char message[64];
} KiwiErr;
const char* message;
bool must_free;
} const* KiwiErrPtr;
typedef struct {
void* impl_;
} KiwiSolverRef;
struct KiwiSolver;
typedef struct KiwiSolver* KiwiSolverPtr;
KiwiVarRef kiwi_var_new(const char* name);
void kiwi_var_del(KiwiVarRef var);
@@ -67,45 +68,30 @@ void kiwi_var_set_value(KiwiVarRef var, double value);
int kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
KiwiConstraintRef
kiwi_constraint_new(const KiwiExpression* expression, enum KiwiRelOp op, double strength);
kiwi_constraint_new(KiwiExpressionConstPtr expression, enum KiwiRelOp op, double strength);
void kiwi_constraint_del(KiwiConstraintRef constraint);
double kiwi_constraint_strength(KiwiConstraintRef constraint);
enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint);
int kiwi_constraint_violated(KiwiConstraintRef constraint);
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpressionPtr out, int out_size);
int kiwi_constraint_expression(
KiwiConstraintRef constraint,
KiwiExpression* out,
int out_size
);
KiwiErrPtr kiwi_solver_add_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
KiwiErrPtr kiwi_solver_remove_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
bool kiwi_solver_has_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
KiwiErrPtr kiwi_solver_add_edit_var(KiwiSolverPtr sp, KiwiVarRef var, double strength);
KiwiErrPtr kiwi_solver_remove_edit_var(KiwiSolverPtr sp, KiwiVarRef var);
bool kiwi_solver_has_edit_var(KiwiSolverPtr sp, KiwiVarRef var);
KiwiErrPtr kiwi_solver_suggest_value(KiwiSolverPtr sp, KiwiVarRef var, double value);
void kiwi_solver_update_vars(KiwiSolverPtr sp);
void kiwi_solver_reset(KiwiSolverPtr sp);
void kiwi_solver_dump(KiwiSolverPtr sp);
char* kiwi_solver_dumps(KiwiSolverPtr sp);
KiwiErr kiwi_solver_add_constraint(KiwiSolverRef s, KiwiConstraintRef constraint);
KiwiErr kiwi_solver_remove_constraint(KiwiSolverRef s, KiwiConstraintRef constraint);
int kiwi_solver_has_constraint(KiwiSolverRef s, KiwiConstraintRef constraint);
KiwiErr kiwi_solver_add_edit_var(KiwiSolverRef s, KiwiVarRef var, double strength);
KiwiErr kiwi_solver_remove_edit_var(KiwiSolverRef s, KiwiVarRef var);
int kiwi_solver_has_edit_var(KiwiSolverRef s, KiwiVarRef var);
KiwiErr kiwi_solver_suggest_value(KiwiSolverRef s, KiwiVarRef var, double value);
void kiwi_solver_update_vars(KiwiSolverRef s);
void kiwi_solver_reset(KiwiSolverRef s);
void kiwi_solver_dump(KiwiSolverRef s);
char* kiwi_solver_dumps(KiwiSolverRef s, void* (*alloc)(size_t));
KiwiSolverRef kiwi_solver_new();
void kiwi_solver_del(KiwiSolverRef s);
KiwiSolverPtr kiwi_solver_new();
void kiwi_solver_del(KiwiSolverPtr sp);
// LuaJIT end
#ifdef __cplusplus