From 301923532897a3c6a6f358c4b4fb6e8a5e80bfba Mon Sep 17 00:00:00 2001 From: Weijia Wang <9713184+wegank@users.noreply.github.com> Date: Mon, 23 Mar 2026 23:12:15 +0100 Subject: [PATCH 1/2] Reject malformed inputs in the term parser --- src/msolve/iofiles.c | 113 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 10 deletions(-) diff --git a/src/msolve/iofiles.c b/src/msolve/iofiles.c index 15c1661c..272ef7c8 100644 --- a/src/msolve/iofiles.c +++ b/src/msolve/iofiles.c @@ -23,29 +23,51 @@ #include "msolve-data.h" #include "streams.h" -static inline void store_exponent(const char *term, data_gens_ff_t *gens, int64_t pos) +#include + +static inline int store_exponent(const char *term, data_gens_ff_t *gens, int64_t pos) { len_t i, j, k; len_t op = 0; + len_t index = 0; + + int res = 0; + mpz_t tmp_z; + mpq_t tmp_q; + if (gens->field_char > 0) { + mpz_init(tmp_z); + } else { + mpq_init(tmp_q); + } + char *var = NULL; char *ev = NULL; + char *end = NULL; for (i = 0; i < strlen(term)+1; ++i) { if (term[i] == '*' || i == strlen(term)) { j = op; while (j < i && term[j] != '^') { ++j; } - if (term[j-1] == ',') { - --j; - } while(term[op] == ' ' || term[op] == '+' || term[op] == '-') { ++op; } + if (op >= j) { + fprintf(stderr, "Error when parsing term %s (missing operand for *)\n", term); + res = 1; + break; + } var = realloc(var, sizeof(char)*(j-op+1)); memcpy(var, term+op, j-op); var[j-op] = '\0'; - if (term[j] == '^') { + int has_exponent = (j < i && term[j] == '^'); + if (has_exponent) { + if (j + 1 >= i) { + fprintf(stderr, "Error when parsing term %s (missing exponent)\n", term); + res = 1; + break; + } ev = realloc(ev, (sizeof(char)*(i-j))); ev = memcpy(ev, term+(j+1), i-j-1); ev[i-j-1] = '\0'; @@ -54,17 +76,76 @@ static inline void store_exponent(const char *term, data_gens_ff_t *gens, int64_ ev[0] = '1'; ev[1] ='\0'; } + int is_var = 0; for (k = 0; k < gens->nvars; ++k) { if (strcmp(gens->vnames[k], var) == 0) { - ((gens->exps) + pos)[k] = strtol(ev, NULL, 10); + is_var = 1; + if (((gens->exps) + pos)[k] != 0) { + fprintf(stderr, "Error when parsing term %s (variable appears multiple times)\n", term); + res = 1; + break; + } + long val = strtol(ev, &end, 10); + if (ev == end) { + fprintf(stderr, "Error when parsing term %s (invalid exponent)\n", term); + res = 1; + break; + } + if (errno == ERANGE || val > INT_MAX) { + fprintf(stderr, "Error when parsing term %s (exponent out of range)\n", term); + res = 1; + break; + } + if (val <= 0) { + fprintf(stderr, "Error when parsing term %s (exponent must be positive)\n", term); + res = 1; + break; + } + ((gens->exps) + pos)[k] = val; break; } } + if (res == 1) { + break; + } + if (is_var == 0) { + if (has_exponent) { + fprintf(stderr, "Error when parsing term %s (coefficient cannot have an exponent)\n", term); + res = 1; + break; + } + if (index > 0) { + fprintf(stderr, "Error when parsing term %s (multiple coefficients are not allowed)\n", term); + res = 1; + break; + } + if (gens->field_char > 0) { + if (mpz_set_str(tmp_z, var, 10) != 0) { + fprintf(stderr, "Error when parsing term %s (invalid coefficient for finite field)\n", term); + res = 1; + break; + } + } else { + if (mpq_set_str(tmp_q, var, 10) != 0) { + fprintf(stderr, "Error when parsing term %s (invalid coefficient)\n", term); + res = 1; + break; + } + } + } op = i+1; + index++; } } + free(var); free(ev); + if (gens->field_char > 0) { + mpz_clear(tmp_z); + } else { + mpq_clear(tmp_q); + } + return res; } @@ -774,7 +855,10 @@ static int get_coefficient_ff_and_term_from_line(char *line, int32_t nterms, iv_tmp += field_char; //MS change int -> long int } gens->cfs[pos] = (int32_t)iv_tmp; - store_exponent(term, gens, pos * (int64_t)gens->nvars); + if (store_exponent(term, gens, pos * (int64_t)gens->nvars)) { + free(term); + return 1; + } for(int64_t j = 1; j < nterms; j++){ get_term(line, &prev_pos, &term, &term_size); if (term != NULL) { @@ -797,7 +881,10 @@ static int get_coefficient_ff_and_term_from_line(char *line, int32_t nterms, cf_tmp += field_char; } gens->cfs[pos+j] = (int32_t)cf_tmp; - store_exponent(term, gens, (pos + j) * (int64_t)gens->nvars); + if (store_exponent(term, gens, (pos + j) * (int64_t)gens->nvars)) { + free(term); + return 1; + } } // store_exponent(term, basis, ht); } @@ -885,11 +972,17 @@ static int get_coefficient_mpz_and_term_from_line(char *line, int32_t nterms, if(term != NULL){ beginning_strterm_to_mpz(term, gens->mpz_cfs[pos], gens->mpz_cfs[pos+1]); - store_exponent(term, gens, (pos / 2) * (int64_t)gens->nvars); + if (store_exponent(term, gens, (pos / 2) * (int64_t)gens->nvars)) { + free(term); + return 1; + } for(int64_t j = 2; j < 2*(int64_t)nterms; j+=2){ get_term(line, &prev_pos, &term, &term_size); inner_strterm_to_mpz(term, gens->mpz_cfs[pos+j], gens->mpz_cfs[pos+j+1]); - store_exponent(term, gens, ((pos + j) / 2) * (int64_t)gens->nvars); + if (store_exponent(term, gens, ((pos + j) / 2) * (int64_t)gens->nvars)) { + free(term); + return 1; + } } free(term); return 0; From e487d032b06cd8e31bb02a3e95d2f49986eb1ba3 Mon Sep 17 00:00:00 2001 From: Weijia Wang <9713184+wegank@users.noreply.github.com> Date: Thu, 1 Oct 2026 02:41:44 +0200 Subject: [PATCH 2/2] Minor fixup following an LLM review Co-Authored-By: Claude Opus 5.5 --- src/msolve/iofiles.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/msolve/iofiles.c b/src/msolve/iofiles.c index 272ef7c8..a52b77f8 100644 --- a/src/msolve/iofiles.c +++ b/src/msolve/iofiles.c @@ -24,6 +24,7 @@ #include "streams.h" #include +#include static inline int store_exponent(const char *term, data_gens_ff_t *gens, int64_t pos) { @@ -54,7 +55,11 @@ static inline int store_exponent(const char *term, data_gens_ff_t *gens, int64_t ++op; } if (op >= j) { - fprintf(stderr, "Error when parsing term %s (missing operand for *)\n", term); + if (index == 0 && term[op] == '\0') { + fprintf(stderr, "Error when parsing term %s (empty term)\n", term); + } else { + fprintf(stderr, "Error when parsing term %s (missing operand)\n", term); + } res = 1; break; } @@ -85,8 +90,9 @@ static inline int store_exponent(const char *term, data_gens_ff_t *gens, int64_t res = 1; break; } + errno = 0; long val = strtol(ev, &end, 10); - if (ev == end) { + if (ev == end || *end != '\0') { fprintf(stderr, "Error when parsing term %s (invalid exponent)\n", term); res = 1; break; @@ -109,29 +115,29 @@ static inline int store_exponent(const char *term, data_gens_ff_t *gens, int64_t break; } if (is_var == 0) { - if (has_exponent) { - fprintf(stderr, "Error when parsing term %s (coefficient cannot have an exponent)\n", term); - res = 1; - break; - } - if (index > 0) { - fprintf(stderr, "Error when parsing term %s (multiple coefficients are not allowed)\n", term); - res = 1; - break; - } if (gens->field_char > 0) { if (mpz_set_str(tmp_z, var, 10) != 0) { - fprintf(stderr, "Error when parsing term %s (invalid coefficient for finite field)\n", term); + fprintf(stderr, "Error when parsing term %s (unknown variable or invalid coefficient for finite field: %s)\n", term, var); res = 1; break; } } else { if (mpq_set_str(tmp_q, var, 10) != 0) { - fprintf(stderr, "Error when parsing term %s (invalid coefficient)\n", term); + fprintf(stderr, "Error when parsing term %s (unknown variable or invalid coefficient: %s)\n", term, var); res = 1; break; } } + if (has_exponent) { + fprintf(stderr, "Error when parsing term %s (coefficient cannot have an exponent)\n", term); + res = 1; + break; + } + if (index > 0) { + fprintf(stderr, "Error when parsing term %s (coefficient must be the first factor)\n", term); + res = 1; + break; + } } op = i+1; index++;