From 6a06fd7a7afc5932e20410ba591475a13e2db51d Mon Sep 17 00:00:00 2001 From: Anders Betts Date: Sun, 20 Sep 2026 09:39:52 +0200 Subject: ledger: free the default-series string on every post error path --- src/ledger.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/ledger.c') diff --git a/src/ledger.c b/src/ledger.c index 4dacde4..2de794e 100644 --- a/src/ledger.c +++ b/src/ledger.c @@ -390,28 +390,37 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, int64_t sum_debit = 0, sum_credit = 0; for (size_t i = 0; i < o->nrows; i++) { const struct ledger_row *r = &o->rows[i]; - if (!r->account || !*r->account) + if (!r->account || !*r->account) { + free(series_owned); return fail(e, "INVALID_ARGS", "row %zu: account is required", i + 1); - if (r->debit_ore < 0 || r->credit_ore < 0) + } + if (r->debit_ore < 0 || r->credit_ore < 0) { + free(series_owned); return fail(e, "INVALID_ARGS", "row %zu: amounts must be positive öre", i + 1); - if ((r->debit_ore == 0) == (r->credit_ore == 0)) + } + if ((r->debit_ore == 0) == (r->credit_ore == 0)) { + free(series_owned); return fail(e, "INVALID_ARGS", "row %zu: exactly one of debit/credit must be set", i + 1); + } sum_debit += r->debit_ore; sum_credit += r->credit_ore; } if (sum_debit != sum_credit) { e->has_details = 1; e->difference_ore = sum_debit - sum_credit; + free(series_owned); return fail(e, "UNBALANCED", "debit and credit differ by %lld öre", (long long)(sum_debit - sum_credit)); } - if (sqlite3_exec(db, "BEGIN IMMEDIATE", NULL, NULL, NULL) != SQLITE_OK) + if (sqlite3_exec(db, "BEGIN IMMEDIATE", NULL, NULL, NULL) != SQLITE_OK) { + free(series_owned); return fail(e, "DB_BUSY", "could not start transaction"); + } int rc = -1; sqlite3_stmt *st = NULL; @@ -435,6 +444,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, if (sqlite3_step(st) != SQLITE_ROW) { sqlite3_finalize(st); sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "DATE_OUT_OF_RANGE", "no fiscal year contains %s; open one first", o->date); } @@ -453,11 +463,13 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, if (strcmp(fy_status, "closed") == 0) { sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "FISCAL_YEAR_CLOSED", "fiscal year %s is closed", fy_label); } if (locked_until[0] && strcmp(o->date, locked_until) <= 0) { sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "PERIOD_LOCKED", "period is locked through %s", locked_until); } @@ -479,6 +491,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, sqlite3_finalize(st); free(acct_ids); sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "ACCOUNT_NOT_FOUND", "account %s does not exist", o->rows[i].account); } @@ -488,6 +501,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, if (!active) { free(acct_ids); sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "ACCOUNT_INACTIVE", "account %s is inactive", o->rows[i].account); } @@ -511,6 +525,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, if (!exists) { free(acct_ids); sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "NOT_FOUND", "voucher %lld does not exist", (long long)o->corrects_voucher_id); } @@ -708,11 +723,13 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, sqlite3_finalize(st); if (!exists) { sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "NOT_FOUND", "attachment %lld does not exist", (long long)aid); } if (linked) { sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + free(series_owned); return fail(e, "CONFLICT", "attachment %lld is already linked", (long long)aid); } -- cgit v1.3