Skip to content

Commit 7acbdc5

Browse files
committed
Fix use-after-free on batch error strings in C addon
ERR_SAVE macro copies error message to stack buffer before cleanup (finalize/rollback) frees the engine's internal string. Fixes garbled error output from dbExecBatchBuf and txExecBatch.
1 parent c636e54 commit 7acbdc5

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

src/stoolap.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <stdlib.h>
1313
#include <string.h>
1414
#include <stdint.h>
15+
#include <stdio.h>
1516

1617
#ifdef _WIN32
1718
#include <windows.h>
@@ -156,6 +157,8 @@ static LibHandle lib_handle = NULL;
156157
/* ---- Helpers ---- */
157158

158159
#define THROW(env, msg) do { napi_throw_error(env, NULL, msg); return NULL; } while(0)
160+
#define ERR_SAVE(msg, fallback) \
161+
char _eb[512]; snprintf(_eb, sizeof(_eb), "%s", (msg) ? (msg) : (fallback))
159162
#define CHECK(env, status) if ((status) != napi_ok) return NULL
160163

161164
static napi_value make_changes(napi_env env, int64_t n) {
@@ -3023,10 +3026,10 @@ static napi_value wrap_tx_exec_batch(napi_env env, napi_callback_info info) {
30233026
for (int k = 0; k < tbuf_cnt; k++) { free(tbufs[k]); tbufs[k] = NULL; }
30243027

30253028
if (rc != STOOLAP_OK) {
3029+
ERR_SAVE(S.tx_errmsg(tx), "Transaction batch exec error");
30263030
free(vals); free(tbufs);
3027-
const char* msg = S.tx_errmsg(tx);
30283031
if (stmt) S.stmt_finalize(stmt);
3029-
THROW(env, msg ? msg : "Transaction batch exec error");
3032+
THROW(env, _eb);
30303033
}
30313034

30323035
total_affected += affected;
@@ -3202,7 +3205,7 @@ static napi_value wrap_db_exec_batch_buf(napi_env env, napi_callback_info info)
32023205
int use_stmt = (S.tx_stmt_exec != NULL);
32033206
if (use_stmt) {
32043207
rc = S.prepare(db, sql, &stmt);
3205-
if (rc != STOOLAP_OK) { S.tx_rollback(tx); const char* msg = S.errmsg(db); THROW(env, msg ? msg : "Prepare error"); }
3208+
if (rc != STOOLAP_OK) { ERR_SAVE(S.errmsg(db), "Prepare error"); S.tx_rollback(tx); THROW(env, _eb); }
32063209
}
32073210
int64_t total = 0;
32083211
for (uint32_t i = 0; i < row_count; i++) {
@@ -3217,12 +3220,12 @@ static napi_value wrap_db_exec_batch_buf(napi_env env, napi_callback_info info)
32173220
} else {
32183221
rc = S.tx_exec_p(tx, sql, vals, decoded, &affected);
32193222
}
3220-
if (rc != STOOLAP_OK) { const char* msg = S.tx_errmsg(tx); if (stmt) S.stmt_finalize(stmt); S.tx_rollback(tx); THROW(env, msg ? msg : "Batch exec error"); }
3223+
if (rc != STOOLAP_OK) { ERR_SAVE(S.tx_errmsg(tx), "Batch exec error"); if (stmt) S.stmt_finalize(stmt); S.tx_rollback(tx); THROW(env, _eb); }
32213224
total += affected;
32223225
}
32233226
if (stmt) S.stmt_finalize(stmt);
32243227
rc = S.tx_commit(tx);
3225-
if (rc != STOOLAP_OK) { const char* msg = S.errmsg(db); THROW(env, msg ? msg : "Commit error"); }
3228+
if (rc != STOOLAP_OK) { THROW(env, "Commit error"); }
32263229
return make_changes(env, total);
32273230
}
32283231

0 commit comments

Comments
 (0)