fix: code quality improvements across C codebase

- Replace sprintf with snprintf (1024-byte errbuf) in hmmmm.c, base_device.c,
  compose_device.c, config.c
- Fix WRITE_MEM macro: use smartAddrWriteHandlers for write ident (was
  incorrectly reading from smartAddrReadHandlers)
- Replace alloca with malloc+free in dispatchMemAccessNotifications
- Guard closeBaseDevice against NULL lib/partial initialization
- Simplify intercept context storage to single contiguous allocation
- Add NULL checks after calloc in config handler with proper cleanup
- Guard find_device_by_id against zero-length path

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-01 22:18:23 +00:00
parent eb7f4b7eb0
commit 71ec472510
7 changed files with 200 additions and 76 deletions

View File

@@ -0,0 +1,105 @@
#ifndef __INSTR_H__
#define __INSTR_H__
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "mem.h"
#ifndef OPCODE_WORDSIZE
#error OPCODE_WORDSIZE must be provided
// #define OPCODE_WORDSIZE 1
#endif
#if OPCODE_WORDSIZE == 1
typedef uint8_t opcode_t;
#elif OPCODE_WORDSIZE == 2
typedef uint16_t opcode_t;
#elif OPCODE_WORDSIZE == 3
typedef uint32_t opcode_t;
#elif OPCODE_WORDSIZE == 4
typedef uint32_t opcode_t;
#else
#error OPCODE_WORDSIZE must be one of 1,2,3,
#endif
#ifndef PC_WORDSIZE
#error PC_WORDSIZE must be provided
// #define PC_WORDSIZE 1
#endif
#if PC_WORDSIZE == 1
typedef uint8_t prog_counter_t;
#elif PC_WORDSIZE == 2
typedef uint16_t prog_counter_t;
#elif PC_WORDSIZE == 3
typedef uint32_t prog_counter_t;
#elif PC_WORDSIZE == 4
typedef uint32_t prog_counter_t;
#else
#error PC_WORDSIZE must be one of 1,2,3,4
#endif
typedef uint8_t (*instr_h_func)(prog_counter_t*, device_mem_t*);
typedef struct
{
instr_h_func h;
opcode_t base;
opcode_t argsMask;
uint8_t opcodeLen;
} instruction_metadata_t;
instr_h_func* genInstrArray(char* errbuf);
void setOpcodeSizes(uint8_t* opcodeSizes);
opcode_t extractOpcode(device_mem_t* devMem, prog_counter_t programCounter);
#define AVRe 1
#define AVRxm 2
#define AVRxt 3
#define AVRrc 4
#ifndef ARCH
#define ARCH AVRe
#endif
#define READ_MEM(__tgt, __mem, __segno, __addr, __cell_t) \
{\
uint64_t __globalAddr = __mem->memsegShifts[__segno] + __addr; \
if (__mem->smartAddrReadHandlers[__globalAddr].func != NULL) \
{ \
__tgt = *(__cell_t*)__mem->smartAddrReadHandlers[__globalAddr].func(__mem->smartAddrReadHandlers[__globalAddr].ident, __addr, __mem->rawCells + __mem->memsegShifts[__segno]); \
} \
else \
{ \
__tgt = ((__cell_t*)__mem->cells[__segno])[__addr]; \
} \
__mem->memreadCellAddrs[__mem->memreadLen] = __globalAddr; \
__mem->memreadLen += 1; \
}
#define WRITE_MEM(__mem, __segno, __addr, __cell_t, __val) \
{ \
uint64_t __globalAddr = __mem->memsegShifts[__segno] + __addr; \
if (__mem->smartAddrWriteHandlers[__globalAddr].func != NULL) \
{ \
__cell_t __dat = (__cell_t)(__val); \
__mem->smartAddrWriteHandlers[__globalAddr].func(__mem->smartAddrWriteHandlers[__globalAddr].ident, __addr, __mem->rawCells + __mem->memsegShifts[__segno], (void*)&__dat); \
} \
else \
{ \
((__cell_t*)__mem->cells[__segno])[__addr] = (__cell_t)(__val); \
} \
__mem->memwriteCellAddrs[__mem->memwriteLen] = __globalAddr; \
__mem->memwriteLen += 1; \
}
#endif // ifndef __INSTR_H__

View File

@@ -32,7 +32,7 @@ typedef struct {
uint8_t** devicesMem;
size_t devicesCount;
void** deviceHandles; // device_handle_t** — dynamically loaded devices
void** interceptCtxs; // intercept_ctx_t** — heap-allocated intercept contexts
void* interceptCtxs; // contiguous intercept_ctx_t array (freed as single block)
size_t interceptCtxCount;
flatcc_builder_t stream_builder;
} EmulContext;

View File

@@ -7,24 +7,31 @@
void closeBaseDevice(device_handle_t* devHandle)
{
if(devHandle == NULL)
{
return;
}
if(devHandle->ctx != NULL)
{
if(devHandle->specs != NULL)
if(devHandle->specs != NULL && devHandle->lib != NULL)
{
devHandle->lib->freeSpecs(devHandle->specs);
}
if(devHandle->ctx->deviceMem != NULL)
if(devHandle->ctx->deviceMem != NULL && devHandle->lib != NULL)
{
devHandle->lib->freeDevMem(devHandle->ctx->deviceMem);
}
free(devHandle->ctx);
}
if(devHandle->lib->extendedHandlers != NULL)
if(devHandle->lib != NULL)
{
free(devHandle->lib->extendedHandlers);
if(devHandle->lib->extendedHandlers != NULL)
{
free(devHandle->lib->extendedHandlers);
}
dlclose(devHandle->lib->_dlhandl);
free(devHandle->lib);
}
dlclose(devHandle->lib->_dlhandl);
free(devHandle->lib);
}
device_handle_t* openBaseDevice(conf_dev_t* devConf, char* errbuf)
@@ -32,7 +39,7 @@ device_handle_t* openBaseDevice(conf_dev_t* devConf, char* errbuf)
device_handle_t* ret = malloc(sizeof(device_handle_t));
if (ret == NULL)
{
sprintf(errbuf, "unable to allocate device handle struct");
snprintf(errbuf, 1024, "unable to allocate device handle struct");
return NULL;
}
@@ -41,7 +48,7 @@ device_handle_t* openBaseDevice(conf_dev_t* devConf, char* errbuf)
device_lib_t* devLib = loadDeviceLib(devConf->libPath, intErrbuf);
if (devLib == NULL)
{
sprintf(errbuf, "unable to load device library %s: %s", devConf->libPath, intErrbuf);
snprintf(errbuf, 1024, "unable to load device library %s: %s", devConf->libPath, intErrbuf);
free(ret);
return NULL;
}
@@ -50,7 +57,7 @@ device_handle_t* openBaseDevice(conf_dev_t* devConf, char* errbuf)
if (devSpecs == NULL)
{
sprintf(errbuf, "device config parse error: %s", intErrbuf);
snprintf(errbuf, 1024, "device config parse error: %s", intErrbuf);
dlclose(devLib->_dlhandl);
free(ret);
free(devLib);

View File

@@ -13,7 +13,7 @@ char** appendId(char** prev, const char* cur, char* errbuf)
prev = malloc(sizeof(char*) * 2);
if(prev == NULL)
{
sprintf(errbuf, "unable to allocate id");
snprintf(errbuf, 1024, "unable to allocate id");
return NULL;
}
prev[0] = NULL;
@@ -29,7 +29,7 @@ char** appendId(char** prev, const char* cur, char* errbuf)
if(new == NULL)
{
sprintf(errbuf, "unable to reallocate id");
snprintf(errbuf, 1024, "unable to reallocate id");
freeComposeId(prev);
return NULL;
}
@@ -40,7 +40,7 @@ char** appendId(char** prev, const char* cur, char* errbuf)
prev[clockIdLen - 1] = malloc(sizeof(char) * (idLen + 1));
if(prev[clockIdLen - 1] == NULL)
{
sprintf(errbuf, "unable to allocate new id entry");
snprintf(errbuf, 1024, "unable to allocate new id entry");
freeComposeId(prev);
return NULL;
}
@@ -91,7 +91,7 @@ device_handle_t** openComposeDevice(compose_dev_conf_t* conf, char* errbuf)
if(devHandlers == NULL)
{
sprintf(errbuf, "unable to allocate dev handlers");
snprintf(errbuf, 1024, "unable to allocate dev handlers");
return NULL;
}
devHandlers[devIdx] = NULL;
@@ -104,7 +104,7 @@ device_handle_t** openComposeDevice(compose_dev_conf_t* conf, char* errbuf)
device_handle_t* devHandle = openBaseDevice(devConf, intErrbuf);
if(devHandle == NULL)
{
sprintf(errbuf, "unable to open base device %s: %s", devConf->id[0], intErrbuf);
snprintf(errbuf, 1024, "unable to open base device %s: %s", devConf->id[0], intErrbuf);
for(size_t j = 0; j < i; j++)
{
closeBaseDevice(devHandlers[j]);

View File

@@ -92,14 +92,14 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
if (dev == NULL)
{
sprintf(errbuf, "unable to allocate device lib struct");
snprintf(errbuf, 1024, "unable to allocate device lib struct");
return NULL;
}
void *handle = dlopen(libpath, RTLD_NOW);
if (!handle) {
sprintf(errbuf, "unable to open dl handle");
snprintf(errbuf, 1024, "unable to open dl handle");
free(dev);
return NULL;
}
@@ -110,7 +110,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *dlsym_init_error = dlerror();
if (dlsym_init_error) {
sprintf(errbuf, "unable to find init symbol: %s", dlsym_init_error);
snprintf(errbuf, 1024, "unable to find init symbol: %s", dlsym_init_error);
dlclose(handle);
free(dev);
return NULL;
@@ -121,7 +121,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *dlsym_maketick_error = dlerror();
if (dlsym_maketick_error) {
sprintf(errbuf, "unable to find makeDeviceTick symbol: %s", dlsym_maketick_error);
snprintf(errbuf, 1024, "unable to find makeDeviceTick symbol: %s", dlsym_maketick_error);
dlclose(handle);
free(dev);
return NULL;
@@ -133,7 +133,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *_dlib_parseSpecsFromConfig_error = dlerror();
if (_dlib_parseSpecsFromConfig_error) {
sprintf(errbuf, "unable to find parseSpecsFromConfig symbol: %s", _dlib_parseSpecsFromConfig_error);
snprintf(errbuf, 1024, "unable to find parseSpecsFromConfig symbol: %s", _dlib_parseSpecsFromConfig_error);
dlclose(handle);
free(dev);
return NULL;
@@ -145,7 +145,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *_dlib_fillSmartReadSpecs_error = dlerror();
if (_dlib_fillSmartReadSpecs_error) {
sprintf(errbuf, "unable to find fillSmartReadSpecs symbol: %s", _dlib_fillSmartReadSpecs_error);
snprintf(errbuf, 1024, "unable to find fillSmartReadSpecs symbol: %s", _dlib_fillSmartReadSpecs_error);
dlclose(handle);
free(dev);
return NULL;
@@ -157,7 +157,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *_dlib_fillSmartWriteSpecs_error = dlerror();
if (_dlib_fillSmartWriteSpecs_error) {
sprintf(errbuf, "unable to find fillSmartWriteSpecs symbol: %s", _dlib_fillSmartWriteSpecs_error);
snprintf(errbuf, 1024, "unable to find fillSmartWriteSpecs symbol: %s", _dlib_fillSmartWriteSpecs_error);
dlclose(handle);
free(dev);
return NULL;
@@ -168,7 +168,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *dlib_deviceType_error = dlerror();
if (dlib_deviceType_error) {
sprintf(errbuf, "unable to find pubDeviceType symbol: %s", dlib_deviceType_error);
snprintf(errbuf, 1024, "unable to find pubDeviceType symbol: %s", dlib_deviceType_error);
dlclose(handle);
free(dev);
return NULL;
@@ -181,7 +181,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *dlib_freeSpecs_error = dlerror();
if (dlib_freeSpecs_error) {
sprintf(errbuf, "unable to find freeSpecs symbol: %s", dlib_freeSpecs_error);
snprintf(errbuf, 1024, "unable to find freeSpecs symbol: %s", dlib_freeSpecs_error);
dlclose(handle);
free(dev);
return NULL;
@@ -192,7 +192,7 @@ device_lib_t* loadDeviceLib(const char *libpath, char* errbuf)
const char *dlib_freeDevMem_error = dlerror();
if (dlib_freeDevMem_error) {
sprintf(errbuf, "unable to find freeDevMem symbol: %s", dlib_freeDevMem_error);
snprintf(errbuf, 1024, "unable to find freeDevMem symbol: %s", dlib_freeDevMem_error);
dlclose(handle);
free(dev);
return NULL;

View File

@@ -44,7 +44,6 @@
#include <string.h>
#include <stdlib.h>
#include <alloca.h>
@@ -263,7 +262,7 @@ void dispatchMemAccessNotifications(EmulContext* emulContext, DeviceSegStreamReg
// printf("No stream regs\n");
return;
}
StreamReg** dispatchRegs = alloca(sizeof(StreamReg*) * deviceRegs->regCount);
StreamReg** dispatchRegs = malloc(sizeof(StreamReg*) * deviceRegs->regCount);
NULL_GUARD(dispatchRegs);
size_t dispatchRegsCnt = 0;
@@ -305,6 +304,7 @@ void dispatchMemAccessNotifications(EmulContext* emulContext, DeviceSegStreamReg
{
dispatchStreamSegment(emulContext, dispatchRegs[i], mem);
}
free(dispatchRegs);
}
int main(int argc, char** argv)

View File

@@ -25,32 +25,32 @@ static conf_dev_t* conf_from_fb(
char* errbuf)
{
conf_dev_t* dc = calloc(1, sizeof(conf_dev_t));
if (!dc) { sprintf(errbuf, "alloc conf_dev_t"); return NULL; }
if (!dc) { snprintf(errbuf, 1024, "alloc conf_dev_t"); return NULL; }
dc->clockDivider = 1;
dc->clockMultipler = 1;
flatbuffers_string_t lp = hmmmm_config_BaseDeviceConfig_libpath(base);
if (!lp) { sprintf(errbuf, "missing libpath"); free(dc); return NULL; }
if (!lp) { snprintf(errbuf, 1024, "missing libpath"); free(dc); return NULL; }
dc->libPath = strdup(lp);
hmmmm_config_MemSegment_vec_t segs = hmmmm_config_BaseDeviceConfig_mem_segments(base);
size_t seg_n = segs ? hmmmm_config_MemSegment_vec_len(segs) : 0;
dc->memConf = calloc(1, sizeof(conf_mem_t));
if (!dc->memConf) { free(dc->libPath); free(dc); sprintf(errbuf, "alloc memConf"); return NULL; }
if (!dc->memConf) { free(dc->libPath); free(dc); snprintf(errbuf, 1024, "alloc memConf"); return NULL; }
dc->memConf->memSegConfs = calloc(seg_n + 1, sizeof(conf_mem_seg_t*));
if (!dc->memConf->memSegConfs) {
free(dc->memConf); free(dc->libPath); free(dc);
sprintf(errbuf, "alloc memSegConfs");
snprintf(errbuf, 1024, "alloc memSegConfs");
return NULL;
}
for (size_t i = 0; i < seg_n; i++) {
hmmmm_config_MemSegment_table_t seg = hmmmm_config_MemSegment_vec_at(segs, i);
conf_mem_seg_t* s = calloc(1, sizeof(conf_mem_seg_t));
if (!s) { sprintf(errbuf, "alloc seg %zu", i); goto fail; }
if (!s) { snprintf(errbuf, 1024, "alloc seg %zu", i); goto fail; }
flatbuffers_string_t sname = hmmmm_config_MemSegment_name(seg);
s->name = strdup(sname ? sname : "");
@@ -96,10 +96,10 @@ static int load_devices_recursive(
hmmmm_config_DeviceEntry_vec_at(entries, i);
flatbuffers_string_t id = hmmmm_config_DeviceEntry_id(entry);
if (!id) { sprintf(errbuf, "device entry missing id"); return -1; }
if (!id) { snprintf(errbuf, 1024, "device entry missing id"); return -1; }
if (st->depth >= MAX_DEPTH) {
sprintf(errbuf, "device tree too deep");
snprintf(errbuf, 1024, "device tree too deep");
return -1;
}
st->path_stack[st->depth] = id;
@@ -110,7 +110,7 @@ static int load_devices_recursive(
if (ctype == hmmmm_config_DeviceConfig_BaseDeviceConfig) {
if (st->count >= MAX_DEVICES) {
sprintf(errbuf, "too many devices");
snprintf(errbuf, 1024, "too many devices");
return -1;
}
@@ -148,7 +148,7 @@ static int load_devices_recursive(
st->path_lens[idx] = st->depth;
st->paths[idx] = calloc(st->depth + 1, sizeof(char*));
if (!st->paths[idx]) {
sprintf(errbuf, "alloc path array");
snprintf(errbuf, 1024, "alloc path array");
return -1;
}
for (size_t p = 0; p < st->depth; p++) {
@@ -167,7 +167,7 @@ static int load_devices_recursive(
return -1;
}
} else {
sprintf(errbuf, "unknown device config type %u", ctype);
snprintf(errbuf, 1024, "unknown device config type %u", ctype);
return -1;
}
@@ -194,6 +194,7 @@ static void free_load_state_paths(LoadState* st)
static size_t find_device_by_id(LoadState* st, const char* id)
{
for (size_t i = 0; i < st->count; i++) {
if (st->path_lens[i] == 0) continue;
// Match by last path component (the device's own ID)
const char* leaf = st->paths[i][st->path_lens[i] - 1];
if (strcmp(leaf, id) == 0) return i;
@@ -233,26 +234,26 @@ static int apply_projections(
uint32_t shift = hmmmm_config_Projection_shift(proj);
if (!base_at || !base_seg || !target_at || !target_seg) {
sprintf(errbuf, "projection %zu: missing field", i);
snprintf(errbuf, 1024, "projection %zu: missing field", i);
return -1;
}
size_t base_idx = find_device_by_id(st, base_at);
if (base_idx == (size_t)~0) {
sprintf(errbuf, "projection %zu: base device '%s' not found", i, base_at);
snprintf(errbuf, 1024, "projection %zu: base device '%s' not found", i, base_at);
return -1;
}
size_t target_idx = find_device_by_id(st, target_at);
if (target_idx == (size_t)~0) {
sprintf(errbuf, "projection %zu: target device '%s' not found", i, target_at);
snprintf(errbuf, 1024, "projection %zu: target device '%s' not found", i, target_at);
return -1;
}
size_t base_seg_idx = find_seg_by_name(
st->handles[base_idx], st->seg_counts[base_idx], base_seg);
if (base_seg_idx == (size_t)~0) {
sprintf(errbuf, "projection %zu: base segment '%s' not found in '%s'",
snprintf(errbuf, 1024, "projection %zu: base segment '%s' not found in '%s'",
i, base_seg, base_at);
return -1;
}
@@ -260,7 +261,7 @@ static int apply_projections(
size_t target_seg_idx = find_seg_by_name(
st->handles[target_idx], st->seg_counts[target_idx], target_seg);
if (target_seg_idx == (size_t)~0) {
sprintf(errbuf, "projection %zu: target segment '%s' not found in '%s'",
snprintf(errbuf, 1024, "projection %zu: target segment '%s' not found in '%s'",
i, target_seg, target_at);
return -1;
}
@@ -324,13 +325,13 @@ static int apply_intercepts(
*out_ctx_count = 0;
if (icpt_n == 0) { *out_ctxs = NULL; return 0; }
if (icpt_n > MAX_INTERCEPTS) {
sprintf(errbuf, "too many intercepts (%zu)", icpt_n);
snprintf(errbuf, 1024, "too many intercepts (%zu)", icpt_n);
return -1;
}
// Allocate array of intercept contexts (one per intercept)
intercept_ctx_t* ctxs = calloc(icpt_n, sizeof(intercept_ctx_t));
if (!ctxs) { sprintf(errbuf, "alloc intercept contexts"); return -1; }
if (!ctxs) { snprintf(errbuf, 1024, "alloc intercept contexts"); return -1; }
for (size_t i = 0; i < icpt_n; i++) {
hmmmm_config_Intercept_table_t icpt =
@@ -349,7 +350,7 @@ static int apply_intercepts(
uint32_t point_addr = hmmmm_config_Intercept_point_addr(icpt);
if (!base_at || !base_seg || !point_at || !point_seg) {
sprintf(errbuf, "intercept %zu: missing field", i);
snprintf(errbuf, 1024, "intercept %zu: missing field", i);
free(ctxs);
return -1;
}
@@ -357,13 +358,13 @@ static int apply_intercepts(
// Resolve base device + segment
size_t base_idx = find_device_by_id(st, base_at);
if (base_idx == (size_t)~0) {
sprintf(errbuf, "intercept %zu: base device '%s' not found", i, base_at);
snprintf(errbuf, 1024, "intercept %zu: base device '%s' not found", i, base_at);
free(ctxs); return -1;
}
size_t base_seg_idx = find_seg_by_name(
st->handles[base_idx], st->seg_counts[base_idx], base_seg);
if (base_seg_idx == (size_t)~0) {
sprintf(errbuf, "intercept %zu: base segment '%s' not found in '%s'",
snprintf(errbuf, 1024, "intercept %zu: base segment '%s' not found in '%s'",
i, base_seg, base_at);
free(ctxs); return -1;
}
@@ -371,13 +372,13 @@ static int apply_intercepts(
// Resolve point device + segment
size_t point_idx = find_device_by_id(st, point_at);
if (point_idx == (size_t)~0) {
sprintf(errbuf, "intercept %zu: point device '%s' not found", i, point_at);
snprintf(errbuf, 1024, "intercept %zu: point device '%s' not found", i, point_at);
free(ctxs); return -1;
}
size_t point_seg_idx = find_seg_by_name(
st->handles[point_idx], st->seg_counts[point_idx], point_seg);
if (point_seg_idx == (size_t)~0) {
sprintf(errbuf, "intercept %zu: point segment '%s' not found in '%s'",
snprintf(errbuf, 1024, "intercept %zu: point segment '%s' not found in '%s'",
i, point_seg, point_at);
free(ctxs); return -1;
}
@@ -402,34 +403,29 @@ static int apply_intercepts(
uint64_t ident = (uint64_t)(uintptr_t)ctx;
// NOTE: WRITE_MEM macro reads ident from smartAddrReadHandlers, not
// smartAddrWriteHandlers. Always set ident on both arrays so that
// write handlers receive the correct context pointer.
base_mem->smartAddrReadHandlers[base_global].ident = ident;
base_mem->smartAddrWriteHandlers[base_global].ident = ident;
if (mode == hmmmm_config_InterceptMode_shadow_replace) {
// Replace: redirect read and/or write
if (op == hmmmm_config_InterceptOp_op_read ||
op == hmmmm_config_InterceptOp_op_both) {
base_mem->smartAddrReadHandlers[base_global].func = intercept_replace_read;
base_mem->smartAddrReadHandlers[base_global].ident = ident;
}
if (op == hmmmm_config_InterceptOp_op_write ||
op == hmmmm_config_InterceptOp_op_both) {
base_mem->smartAddrWriteHandlers[base_global].func = intercept_replace_write;
base_mem->smartAddrWriteHandlers[base_global].ident = ident;
}
} else if (mode == hmmmm_config_InterceptMode_shadow_copy) {
// Copy: only affects writes (read stays at base)
if (op == hmmmm_config_InterceptOp_op_write ||
op == hmmmm_config_InterceptOp_op_both) {
base_mem->smartAddrWriteHandlers[base_global].func = intercept_copy_write;
base_mem->smartAddrWriteHandlers[base_global].ident = ident;
}
} else if (mode == hmmmm_config_InterceptMode_callback) {
// Callback mode: not implemented yet — skip with warning
printf("[CTRL/CONFIG] intercept %zu '%s': callback mode not yet implemented\n",
i, name ? name : "(unnamed)");
} else {
sprintf(errbuf, "intercept %zu: unknown mode %d", i, mode);
snprintf(errbuf, 1024, "intercept %zu: unknown mode %d", i, mode);
free(ctxs); return -1;
}
@@ -450,11 +446,8 @@ static void free_old_config(EmulContext* emulContext)
{
if (emulContext->devicesCount == 0) return;
// Free intercept contexts
// Free intercept context array (single contiguous allocation)
if (emulContext->interceptCtxs) {
for (size_t i = 0; i < emulContext->interceptCtxCount; i++) {
free(emulContext->interceptCtxs[i]);
}
free(emulContext->interceptCtxs);
emulContext->interceptCtxs = NULL;
emulContext->interceptCtxCount = 0;
@@ -493,7 +486,7 @@ void handleConfigCtrlMessage(
// Must be in STILL state
if (*emulContext->emulState != EMUL_STATE_STILL) {
sprintf(errbuf, "config load requires STILL state");
snprintf(errbuf, 1024, "config load requires STILL state");
printf("[CTRL/CONFIG] error: %s\n", errbuf);
size_t msg_len;
@@ -506,7 +499,7 @@ void handleConfigCtrlMessage(
hmmmm_ctrl_config_ctrl_ConfigCtrlMessage_config(msg);
if (!econf) {
sprintf(errbuf, "missing EmulationConfig");
snprintf(errbuf, 1024, "missing EmulationConfig");
printf("[CTRL/CONFIG] error: %s\n", errbuf);
size_t msg_len;
@@ -520,7 +513,7 @@ void handleConfigCtrlMessage(
hmmmm_config_EmulationConfig_root(econf);
if (!root) {
sprintf(errbuf, "missing root ComposeDeviceConfig");
snprintf(errbuf, 1024, "missing root ComposeDeviceConfig");
printf("[CTRL/CONFIG] error: %s\n", errbuf);
size_t msg_len;
@@ -591,32 +584,51 @@ void handleConfigCtrlMessage(
return;
}
// Store intercept contexts for later cleanup
if (icpt_ctxs) {
emulContext->interceptCtxs = calloc(1, sizeof(void*));
emulContext->interceptCtxs[0] = icpt_ctxs;
emulContext->interceptCtxCount = 1;
} else {
emulContext->interceptCtxs = NULL;
emulContext->interceptCtxCount = 0;
}
// Store intercept context array for later cleanup (single contiguous allocation)
emulContext->interceptCtxs = icpt_ctxs;
emulContext->interceptCtxCount = icpt_count;
// Allocate new arrays for EmulContext
size_t dc = st.count;
emulContext->devicesCount = dc;
emulContext->deviceHandles = calloc(dc, sizeof(void*));
emulContext->devicesMem = calloc(dc, sizeof(uint8_t*));
emulContext->deviceHandles = calloc(dc, sizeof(void*));
emulContext->devicesMem = calloc(dc, sizeof(uint8_t*));
emulContext->deviceStreamRegs = calloc(dc, sizeof(DeviceSegStreamReg*));
if (!emulContext->deviceHandles || !emulContext->devicesMem ||
!emulContext->deviceStreamRegs) {
free(emulContext->deviceHandles);
free(emulContext->devicesMem);
free(emulContext->deviceStreamRegs);
emulContext->deviceHandles = NULL;
emulContext->devicesMem = NULL;
emulContext->deviceStreamRegs = NULL;
emulContext->devicesCount = 0;
for (size_t i = 0; i < st.count; i++) {
closeBaseDevice(st.handles[i]);
free(st.handles[i]);
}
free_load_state_paths(&st);
snprintf(errbuf, sizeof(errbuf), "failed to allocate device arrays");
size_t msg_len;
uint8_t* out = fb_build_config_error(nonce, errbuf, &msg_len);
dispatchOutgoingMessage(emulContext->outBufs, ctx->clientId, out, msg_len);
return;
}
for (size_t i = 0; i < dc; i++) {
emulContext->deviceHandles[i] = st.handles[i];
emulContext->devicesMem[i] = st.handles[i]->ctx->deviceMem->rawCells;
DeviceSegStreamReg* dsr = calloc(1, sizeof(DeviceSegStreamReg));
if (!dsr) { emulContext->deviceStreamRegs[i] = NULL; continue; }
dsr->allocatedSize = 4;
dsr->regCount = 0;
dsr->regs = calloc(4, sizeof(StreamReg));
if (!dsr->regs) { free(dsr); emulContext->deviceStreamRegs[i] = NULL; continue; }
emulContext->deviceStreamRegs[i] = dsr;
}