diff --git a/313index-bounds-check.subx b/313index-bounds-check.subx index 6185e969..de9642fd 100644 --- a/313index-bounds-check.subx +++ b/313index-bounds-check.subx @@ -57,3 +57,6 @@ __check-mu-array-bounds:overflow: eb/jump loop/disp8 } # never gets here + +__mu-abort-null-get-base-address: + (abort "null address in 'get'") diff --git a/linux/313index-bounds-check.subx b/linux/313index-bounds-check.subx index 615935b3..1d7384c1 100644 --- a/linux/313index-bounds-check.subx +++ b/linux/313index-bounds-check.subx @@ -84,3 +84,11 @@ __check-mu-array-bounds:overflow: # "81 0/subop/add %esp 4/imm32" # drop function name # # actually save the index addr in reg # "8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32" + +__mu-abort-null-get-base-address: + (write-buffered Stderr "null address in 'get'\n") + (flush Stderr) + # exit(1) + bb/copy-to-ebx 1/imm32 + e8/call syscall_exit/disp32 + # never gets here diff --git a/linux/mu b/linux/mu index a8d00898..2b2b8476 100755 Binary files a/linux/mu and b/linux/mu differ diff --git a/linux/mu.subx b/linux/mu.subx index 2326f4b1..4ccf4854 100644 --- a/linux/mu.subx +++ b/linux/mu.subx @@ -6879,16 +6879,20 @@ test-convert-function-and-type-definition: (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-and-type-definition/6") (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-and-type-definition/7") (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-and-type-definition/8") - (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/9") - (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") - (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13") - (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14") - (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/15") - (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/16") - (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/17") - (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/18") - (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/19") - (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/20") + (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-function-and-type-definition/9") + (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-get-base-address/disp32" "F - test-convert-function-and-type-definition/10") + (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") + (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-function-and-type-definition/12") + (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-get-base-address/disp32" "F - test-convert-function-and-type-definition/13") + (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/14") + (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/15") + (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/16") + (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/17") + (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/18") + (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/19") + (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/20") + (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/21") + (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/22") # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp @@ -29754,17 +29758,35 @@ translate-mu-get-stmt: # out: (addr buffered-file), stmt: (addr stmt) 50/push-eax 51/push-ecx 52/push-edx - # - (emit-indent *(ebp+8) *Curr-block-depth) - (write-buffered *(ebp+8) "8d/copy-address ") # ecx = stmt 8b/-> *(ebp+0xc) 1/r32/ecx + # var base/eax: (addr var) = stmt->inouts->value + (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax + (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax + # if base is in a register, insert a null check + 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register + { + 0f 84/jump-if-= break/disp32 +$translate-mu-get-stmt:emit-null-check-for-register-input: + # emit "81 7/subop/compare %" base->register " 0/imm32\n" + (emit-indent *(ebp+8) *Curr-block-depth) + (write-buffered *(ebp+8) "81 7/subop/compare %") + (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax + (write-buffered *(ebp+8) %eax) + (write-buffered *(ebp+8) " 0/imm32\n") + # + (emit-indent *(ebp+8) *Curr-block-depth) + (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-get-base-address/disp32\n") + } # var offset/edx: int = get offset of stmt (mu-get-offset %ecx) # => eax 89/<- %edx 0/r32/eax # var base/eax: (addr var) = stmt->inouts->value (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax + # + (emit-indent *(ebp+8) *Curr-block-depth) + (write-buffered *(ebp+8) "8d/copy-address ") # if base is in a register 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register { diff --git a/mu_instructions b/mu_instructions index 945528ad..ea58866e 100644 --- a/mu_instructions +++ b/mu_instructions @@ -374,10 +374,14 @@ If a record (product) type T was defined to have elements a, b, c, ... of types T_a, T_b, T_c, ..., then accessing one of those elements f of type T_f: var/reg: (addr T_f) <- get var2/reg2: (addr T), f - => "8d/copy-address *(" reg2 "+" offset(f) ") " reg "/r32" + => "81 7/subop/compare %" reg2 " 0/imm32" + "0f 84/jump-if-= __mu-abort-null-get-base-address/disp32" + "8d/copy-address *(" reg2 "+" offset(f) ") " reg "/r32" var/reg: (addr T_f) <- get var2: T, f => "8d/copy-address *(ebp+" var2.stack-offset "+" offset(f) ") " reg "/r32" +When the base is an address we perform a null check. + # Allocating memory allocate in: (addr handle T)