greenhorn: fix C VM bugs and expand test suite#1
Open
SuperInstance wants to merge 1 commit intomainfrom
Open
Conversation
Bug fixes: - Fix MEMCMP: memcpy(&b,data,4) was reading wrong offset (should be data+4) - Fix MEMSET: remove redundant dead memcpy(&n,data,4) before correct read - Fix main.c: add missing #include <stdlib.h> (build failure) - Add FLUX_ADDI opcode handling (was missing, caused INVALID_OPCODE) - Add register bounds checking: new gr8() function clamps reg indices to 0-15 preventing out-of-bounds memory access on arbitrary bytecode register values Test expansion (22 new tests, 46 total in test_vm): - addi, addi_negative: ADDI immediate instruction - neg_div, neg_mod: signed division and modulo with negatives - mod_zero: modulo by zero error detection - inc_16bit_boundary, dec_16bit_boundary: 16-bit immediate boundaries - shr_negative: arithmetic right shift with negative value - or_xor_not: OR, XOR, NOT bitwise operations - mov_reg: MOV between registers - flags_zero, flags_after_sub_zero: flag state verification - jmp_forward: forward unconditional jump - jlt_taken, jlt_not_taken: JLT conditional branch - jgt_taken: JGT conditional branch - multi_push_pop: multiple push/pop LIFO order - reg_bounds_clamp: out-of-bounds register index safety - cmp_lt_flags, cmp_gt_flags: comparison flag verification - loop_factorial: 5! computation with backward jump loop - fibonacci_10: fibonacci(10)=55 with backward jump loop - movi_large: MOVI with int16 max negative value - nested_call_ret: double CALL/RET to same subroutine All 63 tests passing (46 VM + 5 memory + 12 asm).
| case FLUX_FGE: rd=f8(v); rs1=f8(v); GPR[rd]=(v->regs.fp[rd]>=v->regs.fp[rs1]); break; | ||
| case FLUX_LOAD8: { rd=f8(v); rs1=f8(v); h=flux_mem_get(&v->mem,"heap"); GPR[rd]=h?(int32_t)flux_mem_read_u8(h,GPR[rs1]):0; } break; | ||
| case FLUX_STORE8: { rd=f8(v); rs1=f8(v); h=flux_mem_get(&v->mem,"heap"); if(h) flux_mem_write_u8(h,GPR[rd],(uint8_t)GPR[rs1]); } break; | ||
| case FLUX_CHECK_TYPE: rd=gr8(v); rs1=f8(v); GPR[0]=(rd<v->box_count&&v->box_table[rd].type_tag==rs1); break; |
There was a problem hiding this comment.
🔴 FLUX_CHECK_TYPE uses gr8() for box ID operand, clamping valid box indices 16-63 to 0
The FLUX_CHECK_TYPE handler reads its first operand (a box table index) using gr8(v), which clamps values >= FLUX_GP_COUNT (16) to 0. However, rd here is NOT a register index — it's a box ID used to index v->box_table[rd] (which supports up to 64 entries per FLUX_BOX_MAX at include/flux/vm.h:18). Any bytecode that calls CHECK_TYPE on box IDs 16–63 will silently check box 0 instead, producing incorrect type-check results. The old code correctly used f8(v) for this operand.
Suggested change
| case FLUX_CHECK_TYPE: rd=gr8(v); rs1=f8(v); GPR[0]=(rd<v->box_count&&v->box_table[rd].type_tag==rs1); break; | |
| case FLUX_CHECK_TYPE: rd=f8(v); rs1=f8(v); GPR[0]=(rd<v->box_count&&v->box_table[rd].type_tag==rs1); break; |
Was this helpful? React with 👍 or 👎 to provide feedback.
Debug
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug Fixes
src/vm.cline 126):memcpy(&b,data,4)was copying addressaintobinstead of the actualbvalue fromdata+4src/vm.cline 125): Removed redundantmemcpy(&n,data,4)that was immediately overwritten by the correctmemcpy(&n,data+4,4)src/main.c): Added missing#include <stdlib.h>formalloc/freesrc/vm.c): AddedFLUX_ADDI(0x19) handler — was falling through toINVALID_OPCODEerrorsrc/vm.c): Newgr8()function clamps register indices to 0-15 (FLUX_GP_COUNT), preventing out-of-bounds memory access when bytecode specifies arbitrary register numbers. Applied to all arithmetic, bitwise, compare, float, stack, and jump instructions.Test Expansion
Added 22 new tests to
tests/test_vm.c(46 total, up from 24):addi,addi_negative— ADDI immediate instructionneg_div,neg_mod— signed division/modulo with negative operandsmod_zero— modulo-by-zero error detectioninc_16bit_boundary,dec_16bit_boundary— int16 immediate boundary valuesshr_negative— arithmetic right shift of negative numbersor_xor_not— OR, XOR, NOT bitwise operationsmov_reg— MOV between different registersflags_zero,flags_after_sub_zero— zero/sign flag state verificationjmp_forward— forward unconditional jumpjlt_taken,jlt_not_taken,jgt_taken— conditional branch testsmulti_push_pop— LIFO stack ordering with 3 valuesreg_bounds_clamp— out-of-bounds register index safetycmp_lt_flags,cmp_gt_flags— comparison flag verificationloop_factorial— 5! = 120 via backward-jump loopfibonacci_10— fibonacci(10) = 55 via backward-jump loopmovi_large— MOVI with -32768 (int16 min)nested_call_ret— double CALL/RET to same subroutineResults
All 63 tests passing (46 VM + 5 memory + 12 assembler)