summaryrefslogtreecommitdiff
path: root/src/ledger.c
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-20 09:39:52 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-20 09:39:52 +0200
commit6a06fd7a7afc5932e20410ba591475a13e2db51d (patch)
treef8357df9a4bd691fd3c14660d682394fc76063c8 /src/ledger.c
parentcc0bf3467b33c32922ec78eb0cf4fffbd90483c2 (diff)
downloadbokf-6a06fd7a7afc5932e20410ba591475a13e2db51d.tar.gz
bokf-6a06fd7a7afc5932e20410ba591475a13e2db51d.zip
ledger: free the default-series string on every post error path
Diffstat (limited to 'src/ledger.c')
-rw-r--r--src/ledger.c25
1 files changed, 21 insertions, 4 deletions
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);
}