#!/usr/bin/env python3 """Exact production stop/start/process-slot functions with retained-resource doubles.""" from pathlib import Path import re import subprocess import tempfile root=Path(__file__).resolve().parents[2] source=(root/'src/ssh_transport.c').read_text() def function(name): m=re.search(r'^static [^\n]+\b'+name+r'\([^;]*?\n\{.*?^\}',source,re.M|re.S) assert m,name return m.group()+'\n' fakes=r''' #include #include #include #include #define SSH_TRANSPORT_MAX_SESSIONS 2 #define SSH_TRANSPORT_SESSION_FREE 0 #define SSH_TRANSPORT_SESSION_CLOSING 3 #define SSH_TRANSPORT_SESSION_HANDSHAKE 1 #define SSH_TRANSPORT_SESSION_ACTIVE 2 #define ESP_OK 0 #define ESP_FAIL 1 #define ESP_ERR_TIMEOUT 2 #define ESP_ERR_INVALID_STATE 3 #define pdMS_TO_TICKS(n) (n) typedef int esp_err_t; typedef struct { int state; bool close_requested; } ssh_slot_t; static ssh_slot_t s_slots[2]; static void *s_context; static int s_listen_fd=-1, s_lock; static unsigned depth, frees, creates; static bool s_running, s_cleanup_pending, cleanup_fail, listener_fail; #define taskENTER_CRITICAL(p) do { (void)(p); assert(!depth++); } while(0) #define taskEXIT_CRITICAL(p) do { (void)(p); assert(!--depth); } while(0) static void wolfSSH_CTX_free(void *p) { assert(!depth && p==s_context); for(unsigned i=0;i<2;++i) assert(!s_slots[i].state); ++frees; } static void close_socket(int *fd) { assert(!depth); *fd=-1; } static void vTaskDelay(unsigned n) { (void)n; assert(!depth); } static void request_slot_close(ssh_slot_t *s,bool revoked) { (void)revoked; if(s->state)s->close_requested=true; } static bool cleanup_slot(ssh_slot_t *s) { if(cleanup_fail)return false; s->state=0;return true; } static void publish_slot(ssh_slot_t *s,size_t i) { (void)s;(void)i; } static bool consume_external_close(ssh_slot_t *s,size_t i) { (void)s;(void)i;return false; } static void process_handshake(ssh_slot_t *s,size_t i) { (void)s;(void)i;assert(0); } static void process_active(ssh_slot_t *s,size_t i) { (void)s;(void)i;assert(0); } static esp_err_t create_context(void) { assert(!s_context && !depth); ++creates;s_context=(void *)1;return ESP_OK; } static esp_err_t create_listener(void) { if(listener_fail)return ESP_FAIL;s_listen_fd=22;return ESP_OK; } ''' tests=r''' int main(void) { assert(start_runtime()==ESP_OK && creates==1); assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==1 && !frees); s_slots[0].state=2;cleanup_fail=true; assert(stop_runtime()==ESP_ERR_TIMEOUT && s_context && !frees && s_listen_fd==-1); s_cleanup_pending=true;s_running=false; assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==1); process_slots();assert(s_context && s_cleanup_pending && !frees); cleanup_fail=false;process_slots();assert(!s_context && !s_cleanup_pending && frees==1); process_slots();assert(frees==1); assert(start_runtime()==ESP_OK && creates==2);assert(stop_runtime()==ESP_OK && frees==2); listener_fail=true;assert(start_runtime()==ESP_FAIL && !s_context && frees==3 && s_listen_fd==-1); s_slots[1].state=2;assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==3);s_slots[1].state=0; s_listen_fd=22;assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==3); puts("PASS SSH actual runtime stop failure retains context, rejects orphan overwrite, owner retires only after all slots free, failed listener frees context exactly once"); } ''' with tempfile.TemporaryDirectory(prefix='ssh-runtime-') as directory: out=Path(directory) (out/'test.c').write_text(fakes+''.join(function(n) for n in ('start_runtime','stop_runtime','process_slots'))+tests) subprocess.run(['cc','-std=c11','-Wall','-Wextra','-Werror',str(out/'test.c'),'-o',str(out/'test')],check=True,timeout=30) subprocess.run([str(out/'test')],check=True,timeout=10)