From 71ec4725108bd9936a9293ebfc5aa37a562b35e0 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 1 Apr 2026 22:18:23 +0000 Subject: [PATCH] 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 --- devices/avr_generic/inc/instr.h | 105 ++++++++++++++++++++++++++++++ inc/context.h | 2 +- src/base_device.c | 25 +++++--- src/compose_device.c | 10 +-- src/hmmmm.c | 20 +++--- src/main.c | 4 +- src/proto/handlers/config.c | 110 ++++++++++++++++++-------------- 7 files changed, 200 insertions(+), 76 deletions(-) create mode 100644 devices/avr_generic/inc/instr.h diff --git a/devices/avr_generic/inc/instr.h b/devices/avr_generic/inc/instr.h new file mode 100644 index 0000000..a712cfc --- /dev/null +++ b/devices/avr_generic/inc/instr.h @@ -0,0 +1,105 @@ +#ifndef __INSTR_H__ +#define __INSTR_H__ + +#include +#include +#include +#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__ \ No newline at end of file diff --git a/inc/context.h b/inc/context.h index 4106079..683f285 100644 --- a/inc/context.h +++ b/inc/context.h @@ -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; diff --git a/src/base_device.c b/src/base_device.c index ee8664b..91d9352 100644 --- a/src/base_device.c +++ b/src/base_device.c @@ -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); diff --git a/src/compose_device.c b/src/compose_device.c index c9ce1c1..770da1d 100644 --- a/src/compose_device.c +++ b/src/compose_device.c @@ -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]); diff --git a/src/hmmmm.c b/src/hmmmm.c index 99713f7..5d5cb99 100644 --- a/src/hmmmm.c +++ b/src/hmmmm.c @@ -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; diff --git a/src/main.c b/src/main.c index 5c4f191..35af965 100644 --- a/src/main.c +++ b/src/main.c @@ -44,7 +44,6 @@ #include #include -#include @@ -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) diff --git a/src/proto/handlers/config.c b/src/proto/handlers/config.c index 0a61f22..b9aea10 100644 --- a/src/proto/handlers/config.c +++ b/src/proto/handlers/config.c @@ -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; }