11/* SPDX-FileCopyrightText: 2026 Frogfish */
22/* SPDX-License-Identifier: GPL-3.0-or-later */
33
4+ #include <inttypes.h>
45#include <limits.h>
56#include <stdint.h>
7+ #include <stdio.h>
68#include <string.h>
79
810#include "zem_exec_internal.h"
@@ -66,6 +68,16 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
6668 uint32_t key_len_u = 0 ;
6769 if (!zabi_u32_from_u64 (regs -> HL , & key_ptr ) ||
6870 !zabi_u32_from_u64 (regs -> DE , & key_len_u )) {
71+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
72+ "key_ptr/key_len not representable as u32" )) {
73+ return 1 ;
74+ }
75+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
76+ fprintf (stderr , " HL(key_ptr)=0x%016" PRIx64 " DE(key_len)=0x%016" PRIx64 "\n" ,
77+ regs -> HL , regs -> DE );
78+ zem_diag_print_regprov (stderr , regprov , "HL" );
79+ zem_diag_print_regprov (stderr , regprov , "DE" );
80+ }
6981 regs -> HL = (uint64_t )(uint32_t )ZI_E_INVALID ;
7082 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
7183 r -> m );
@@ -74,6 +86,16 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
7486 }
7587 int32_t key_len = (int32_t )key_len_u ;
7688 if (key_len < 0 || !mem_check_span (mem , key_ptr , (uint32_t )key_len )) {
89+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
90+ "key span out of bounds" )) {
91+ return 1 ;
92+ }
93+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
94+ fprintf (stderr , " key_ptr=%" PRIu32 " key_len=%" PRId32 " mem_len=%zu\n" ,
95+ key_ptr , key_len , mem ? mem -> len : 0 );
96+ zem_diag_print_regprov (stderr , regprov , "HL" );
97+ zem_diag_print_regprov (stderr , regprov , "DE" );
98+ }
7799 regs -> HL = (uint64_t )(uint32_t )ZI_E_BOUNDS ;
78100 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
79101 r -> m );
@@ -108,6 +130,20 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
108130 !zabi_u32_from_u64 (regs -> DE , & key_len_u ) ||
109131 !zabi_u32_from_u64 (regs -> BC , & out_ptr ) ||
110132 !zabi_u32_from_u64 (regs -> IX , & out_cap_u )) {
133+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
134+ "key/out args not representable as u32" )) {
135+ return 1 ;
136+ }
137+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
138+ fprintf (stderr ,
139+ " HL(key_ptr)=0x%016" PRIx64 " DE(key_len)=0x%016" PRIx64
140+ " BC(out_ptr)=0x%016" PRIx64 " IX(out_cap)=0x%016" PRIx64 "\n" ,
141+ regs -> HL , regs -> DE , regs -> BC , regs -> IX );
142+ zem_diag_print_regprov (stderr , regprov , "HL" );
143+ zem_diag_print_regprov (stderr , regprov , "DE" );
144+ zem_diag_print_regprov (stderr , regprov , "BC" );
145+ zem_diag_print_regprov (stderr , regprov , "IX" );
146+ }
111147 regs -> HL = (uint64_t )(uint32_t )ZI_E_INVALID ;
112148 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
113149 r -> m );
@@ -118,6 +154,20 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
118154 int32_t out_cap = (int32_t )out_cap_u ;
119155 if (key_len < 0 || out_cap < 0 ||
120156 !mem_check_span (mem , key_ptr , (uint32_t )key_len )) {
157+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
158+ "key span out of bounds (or negative lens)" )) {
159+ return 1 ;
160+ }
161+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
162+ fprintf (stderr ,
163+ " key_ptr=%" PRIu32 " key_len=%" PRId32 " out_ptr=%" PRIu32
164+ " out_cap=%" PRId32 " mem_len=%zu\n" ,
165+ key_ptr , key_len , out_ptr , out_cap , mem ? mem -> len : 0 );
166+ zem_diag_print_regprov (stderr , regprov , "HL" );
167+ zem_diag_print_regprov (stderr , regprov , "DE" );
168+ zem_diag_print_regprov (stderr , regprov , "BC" );
169+ zem_diag_print_regprov (stderr , regprov , "IX" );
170+ }
121171 regs -> HL = (uint64_t )(uint32_t )ZI_E_BOUNDS ;
122172 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
123173 r -> m );
@@ -182,6 +232,14 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
182232 if (trace_enabled && trace_pending && trace_meta ) trace_meta -> call_is_prim = 1 ;
183233 uint32_t index = 0 ;
184234 if (!zabi_u32_from_u64 (regs -> HL , & index )) {
235+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
236+ "index not representable as u32" )) {
237+ return 1 ;
238+ }
239+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
240+ fprintf (stderr , " HL(index)=0x%016" PRIx64 "\n" , regs -> HL );
241+ zem_diag_print_regprov (stderr , regprov , "HL" );
242+ }
185243 regs -> HL = (uint64_t )(uint32_t )ZI_E_INVALID ;
186244 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
187245 r -> m );
@@ -212,6 +270,19 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
212270 if (!zabi_u32_from_u64 (regs -> HL , & index ) ||
213271 !zabi_u32_from_u64 (regs -> DE , & out_ptr ) ||
214272 !zabi_u32_from_u64 (regs -> BC , & out_cap_u )) {
273+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
274+ "index/out_ptr/out_cap not representable as u32" )) {
275+ return 1 ;
276+ }
277+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
278+ fprintf (stderr ,
279+ " HL(index)=0x%016" PRIx64 " DE(out_ptr)=0x%016" PRIx64
280+ " BC(out_cap)=0x%016" PRIx64 "\n" ,
281+ regs -> HL , regs -> DE , regs -> BC );
282+ zem_diag_print_regprov (stderr , regprov , "HL" );
283+ zem_diag_print_regprov (stderr , regprov , "DE" );
284+ zem_diag_print_regprov (stderr , regprov , "BC" );
285+ }
215286 regs -> HL = (uint64_t )(uint32_t )ZI_E_INVALID ;
216287 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
217288 r -> m );
@@ -220,6 +291,14 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
220291 }
221292 int32_t out_cap = (int32_t )out_cap_u ;
222293 if (out_cap < 0 ) {
294+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
295+ "out_cap negative" )) {
296+ return 1 ;
297+ }
298+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
299+ fprintf (stderr , " out_cap=%" PRId32 "\n" , out_cap );
300+ zem_diag_print_regprov (stderr , regprov , "BC" );
301+ }
223302 regs -> HL = (uint64_t )(uint32_t )ZI_E_INVALID ;
224303 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
225304 r -> m );
@@ -242,6 +321,16 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
242321 return 1 ;
243322 }
244323 if (!mem_check_span (mem , out_ptr , (uint32_t )n )) {
324+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
325+ "out_ptr span out of bounds" )) {
326+ return 1 ;
327+ }
328+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
329+ fprintf (stderr ,
330+ " out_ptr=%" PRIu32 " n=%zu mem_len=%zu\n" ,
331+ out_ptr , n , mem ? mem -> len : 0 );
332+ zem_diag_print_regprov (stderr , regprov , "DE" );
333+ }
245334 regs -> HL = (uint64_t )(uint32_t )ZI_E_BOUNDS ;
246335 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
247336 r -> m );
@@ -308,7 +397,23 @@ int zem_exec_call_env_time_proc(zem_exec_ctx_t *ctx, const record_t *r,
308397
309398 if (strcmp (callee , "zi_time_sleep_ms" ) == 0 ) {
310399 if (trace_enabled && trace_pending && trace_meta ) trace_meta -> call_is_prim = 1 ;
311- zi_time_ms += (uint32_t )regs -> HL ;
400+ uint32_t delta_ms = 0 ;
401+ if (!zabi_u32_from_u64 (regs -> HL , & delta_ms )) {
402+ if (zem_sniff_abi_fail_or_warn (ctx , r , pc , callee , cur_label ,
403+ "delta_ms not representable as u32" )) {
404+ return 1 ;
405+ }
406+ if (ctx -> dbg_cfg && ctx -> dbg_cfg -> sniff ) {
407+ fprintf (stderr , " HL(delta_ms)=0x%016" PRIx64 "\n" , regs -> HL );
408+ zem_diag_print_regprov (stderr , regprov , "HL" );
409+ }
410+ regs -> HL = (uint64_t )(uint32_t )ZI_E_INVALID ;
411+ zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
412+ r -> m );
413+ * ctx -> pc = pc + 1 ;
414+ return 1 ;
415+ }
416+ zi_time_ms += delta_ms ;
312417 regs -> HL = (uint64_t )(uint32_t )ZI_OK ;
313418 zem_regprov_note (regprov , ZEM_REG_HL , (uint32_t )pc , cur_label , r -> line ,
314419 r -> m );
0 commit comments