solver-c: harden parser/io and numerical output entrypoints
Improve stdin/file JSON ingestion safety and guard output paths against edge-case assumptions so solver binaries fail predictably instead of risking malformed reads. Made-with: Cursor
This commit is contained in:
@@ -9,30 +9,49 @@
|
|||||||
#define JSON_MAX_SIZE (4 * 1024 * 1024)
|
#define JSON_MAX_SIZE (4 * 1024 * 1024)
|
||||||
|
|
||||||
int solver_read_json_stdin(char **buffer_out, size_t *length_out) {
|
int solver_read_json_stdin(char **buffer_out, size_t *length_out) {
|
||||||
size_t cap = JSON_READ_CHUNK;
|
size_t cap = JSON_READ_CHUNK + 1;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char *buf = (char *)malloc(cap);
|
char *buf = (char *)malloc(cap);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
size_t n = fread(buf + len, 1, JSON_READ_CHUNK, stdin);
|
size_t remaining = (cap > len) ? (cap - len - 1) : 0;
|
||||||
len += n;
|
if (remaining == 0) {
|
||||||
if (n < JSON_READ_CHUNK) {
|
if (cap > JSON_MAX_SIZE) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (len + JSON_READ_CHUNK > JSON_MAX_SIZE) {
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if (len + JSON_READ_CHUNK > cap) {
|
size_t next_cap = cap * 2;
|
||||||
cap *= 2;
|
if (next_cap > JSON_MAX_SIZE + 1) {
|
||||||
char *nb = (char *)realloc(buf, cap);
|
next_cap = JSON_MAX_SIZE + 1;
|
||||||
|
}
|
||||||
|
if (next_cap <= cap) {
|
||||||
|
free(buf);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
char *nb = (char *)realloc(buf, next_cap);
|
||||||
if (!nb) {
|
if (!nb) {
|
||||||
free(buf);
|
free(buf);
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
buf = nb;
|
buf = nb;
|
||||||
|
cap = next_cap;
|
||||||
|
remaining = cap - len - 1;
|
||||||
|
}
|
||||||
|
size_t to_read = remaining < JSON_READ_CHUNK ? remaining : JSON_READ_CHUNK;
|
||||||
|
size_t n = fread(buf + len, 1, to_read, stdin);
|
||||||
|
len += n;
|
||||||
|
if (ferror(stdin)) {
|
||||||
|
free(buf);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (n < to_read) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (len >= JSON_MAX_SIZE) {
|
||||||
|
free(buf);
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
|
|||||||
@@ -4,6 +4,40 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static int read_json_file(const char *path, char **buf_out) {
|
||||||
|
FILE *fp = fopen(path, "rb");
|
||||||
|
if (!fp) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
long sz = ftell(fp);
|
||||||
|
if (sz < 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (fseek(fp, 0, SEEK_SET) != 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
char *buf = (char *)malloc((size_t)sz + 1);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(fp);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
size_t n = fread(buf, 1, (size_t)sz, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (n != (size_t)sz) {
|
||||||
|
free(buf);
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
buf[sz] = '\0';
|
||||||
|
*buf_out = buf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void print_json_output(const SolverInputs *inputs, const SolverOutputs *outputs) {
|
static void print_json_output(const SolverInputs *inputs, const SolverOutputs *outputs) {
|
||||||
printf("{\n");
|
printf("{\n");
|
||||||
printf(" \"pointCount\": %d,\n", outputs->point_count);
|
printf(" \"pointCount\": %d,\n", outputs->point_count);
|
||||||
@@ -33,8 +67,12 @@ static void print_json_output(const SolverInputs *inputs, const SolverOutputs *o
|
|||||||
}
|
}
|
||||||
printf(" ],\n");
|
printf(" ],\n");
|
||||||
|
|
||||||
double pmin = outputs->pump_position_m[0];
|
double pmin = 0.0;
|
||||||
double pmax = outputs->pump_position_m[0];
|
double pmax = 0.0;
|
||||||
|
if (outputs->point_count > 0) {
|
||||||
|
pmin = outputs->pump_position_m[0];
|
||||||
|
pmax = outputs->pump_position_m[0];
|
||||||
|
}
|
||||||
for (int i = 1; i < outputs->point_count; i++) {
|
for (int i = 1; i < outputs->point_count; i++) {
|
||||||
if (outputs->pump_position_m[i] < pmin) pmin = outputs->pump_position_m[i];
|
if (outputs->pump_position_m[i] < pmin) pmin = outputs->pump_position_m[i];
|
||||||
if (outputs->pump_position_m[i] > pmax) pmax = outputs->pump_position_m[i];
|
if (outputs->pump_position_m[i] > pmax) pmax = outputs->pump_position_m[i];
|
||||||
@@ -143,18 +181,11 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
} else if (argc == 2) {
|
} else if (argc == 2) {
|
||||||
/* allow file path for tests */
|
/* allow file path for tests */
|
||||||
FILE *fp = fopen(argv[1], "rb");
|
int rr = read_json_file(argv[1], &buf);
|
||||||
if (!fp) {
|
if (rr != 0) {
|
||||||
fprintf(stderr, "usage: solver_main --stdin OR solver_main <path.json>\n");
|
fprintf(stderr, "usage: solver_main --stdin OR solver_main <path.json>\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
long sz = ftell(fp);
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
buf = (char *)malloc((size_t)sz + 1);
|
|
||||||
fread(buf, 1, (size_t)sz, fp);
|
|
||||||
fclose(fp);
|
|
||||||
buf[sz] = '\0';
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "usage: solver_main --stdin OR solver_main <path.json>\n");
|
fprintf(stderr, "usage: solver_main --stdin OR solver_main <path.json>\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -4,6 +4,40 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static int read_json_file(const char *path, char **buf_out) {
|
||||||
|
FILE *fp = fopen(path, "rb");
|
||||||
|
if (!fp) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
long sz = ftell(fp);
|
||||||
|
if (sz < 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (fseek(fp, 0, SEEK_SET) != 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
char *buf = (char *)malloc((size_t)sz + 1);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(fp);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
size_t n = fread(buf, 1, (size_t)sz, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (n != (size_t)sz) {
|
||||||
|
free(buf);
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
buf[sz] = '\0';
|
||||||
|
*buf_out = buf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void print_json_output(const SolverInputs *inputs, const SolverOutputs *outputs) {
|
static void print_json_output(const SolverInputs *inputs, const SolverOutputs *outputs) {
|
||||||
printf("{\n");
|
printf("{\n");
|
||||||
printf(" \"pointCount\": %d,\n", outputs->point_count);
|
printf(" \"pointCount\": %d,\n", outputs->point_count);
|
||||||
@@ -33,8 +67,12 @@ static void print_json_output(const SolverInputs *inputs, const SolverOutputs *o
|
|||||||
}
|
}
|
||||||
printf(" ],\n");
|
printf(" ],\n");
|
||||||
|
|
||||||
double pmin = outputs->pump_position_m[0];
|
double pmin = 0.0;
|
||||||
double pmax = outputs->pump_position_m[0];
|
double pmax = 0.0;
|
||||||
|
if (outputs->point_count > 0) {
|
||||||
|
pmin = outputs->pump_position_m[0];
|
||||||
|
pmax = outputs->pump_position_m[0];
|
||||||
|
}
|
||||||
for (int i = 1; i < outputs->point_count; i++) {
|
for (int i = 1; i < outputs->point_count; i++) {
|
||||||
if (outputs->pump_position_m[i] < pmin) pmin = outputs->pump_position_m[i];
|
if (outputs->pump_position_m[i] < pmin) pmin = outputs->pump_position_m[i];
|
||||||
if (outputs->pump_position_m[i] > pmax) pmax = outputs->pump_position_m[i];
|
if (outputs->pump_position_m[i] > pmax) pmax = outputs->pump_position_m[i];
|
||||||
@@ -142,18 +180,11 @@ int main(int argc, char **argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (argc == 2) {
|
} else if (argc == 2) {
|
||||||
FILE *fp = fopen(argv[1], "rb");
|
int rr = read_json_file(argv[1], &buf);
|
||||||
if (!fp) {
|
if (rr != 0) {
|
||||||
fprintf(stderr, "usage: solver_fea_main --stdin OR solver_fea_main <path.json>\n");
|
fprintf(stderr, "usage: solver_fea_main --stdin OR solver_fea_main <path.json>\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
long sz = ftell(fp);
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
buf = (char *)malloc((size_t)sz + 1);
|
|
||||||
fread(buf, 1, (size_t)sz, fp);
|
|
||||||
fclose(fp);
|
|
||||||
buf[sz] = '\0';
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "usage: solver_fea_main --stdin OR solver_fea_main <path.json>\n");
|
fprintf(stderr, "usage: solver_fea_main --stdin OR solver_fea_main <path.json>\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user