about summary refs log tree commit diff stats
path: root/linux
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-05-07 21:04:45 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-05-07 21:04:45 -0700
commit888b4cd8eabff44ad10954f26bd4df4497e28617 (patch)
tree6e890232896f4cfdaa51fad4bcd25fd981b0ef2a /linux
parent61a68452ae84df936e1861e65a331959643ae016 (diff)
downloadmu-888b4cd8eabff44ad10954f26bd4df4497e28617.tar.gz
always check for null in 'index' instructions
Diffstat (limited to 'linux')
-rw-r--r--linux/313index-bounds-check.subx8
-rwxr-xr-xlinux/mubin604512 -> 607182 bytes
-rw-r--r--linux/mu.subx198
3 files changed, 120 insertions, 86 deletions
diff --git a/linux/313index-bounds-check.subx b/linux/313index-bounds-check.subx
index 1d7384c1..377d5adb 100644
--- a/linux/313index-bounds-check.subx
+++ b/linux/313index-bounds-check.subx
@@ -85,6 +85,14 @@ __check-mu-array-bounds:overflow:
 #            # actually save the index addr in reg
 #            "8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32"
 
+__mu-abort-null-index-base-address:
+    (write-buffered Stderr "null address in 'index'\n")
+    (flush Stderr)
+    # exit(1)
+    bb/copy-to-ebx 1/imm32
+    e8/call syscall_exit/disp32
+    # never gets here
+
 __mu-abort-null-get-base-address:
     (write-buffered Stderr "null address in 'get'\n")
     (flush Stderr)
diff --git a/linux/mu b/linux/mu
index 2b2b8476..74374bee 100755
--- a/linux/mu
+++ b/linux/mu
Binary files differdiff --git a/linux/mu.subx b/linux/mu.subx
index 4ccf4854..07ba75a8 100644
--- a/linux/mu.subx
+++ b/linux/mu.subx
@@ -6309,15 +6309,17 @@ test-convert-index-into-array:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array/11")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array/12")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/13")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/14")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/15")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/16")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/17")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/18")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/19")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/20")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/21")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -6359,15 +6361,17 @@ test-convert-index-into-array-of-bytes:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes/10")
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/11")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes/11")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes/12")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/13")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/14")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/15")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/16")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/17")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/18")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/19")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/20")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/21")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -6406,15 +6410,17 @@ test-convert-index-into-array-with-literal:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-with-literal/8")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-with-literal/9")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-with-literal/10")
                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/11")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/12")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/13")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/14")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/15")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/16")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/17")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/18")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -6453,15 +6459,17 @@ test-convert-index-into-array-of-bytes-with-literal:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-with-literal/7")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-with-literal/9")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-with-literal/10")
                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/11")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/12")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/13")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/14")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/15")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/16")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/17")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/18")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -6669,15 +6677,17 @@ test-convert-index-into-array-using-offset:
     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset/11")
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/12")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset/12")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset/13")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/15")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/16")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/17")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/18")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/19")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/20")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/21")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/22")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/23")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -6721,15 +6731,17 @@ test-convert-index-into-array-of-bytes-using-offset:
     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset/9")
     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/10")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset/13")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/14")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/15")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/16")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/17")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/19")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/20")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/21")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/22")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -6773,16 +6785,18 @@ test-convert-index-into-array-using-offset-on-stack:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset-on-stack/10")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset-on-stack/11")
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
-    (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/14")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset-on-stack/13")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/14")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
+    (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/16")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/17")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/18")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/20")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/21")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/22")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/23")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -6826,16 +6840,18 @@ test-convert-index-into-array-of-bytes-using-offset-on-stack:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/9")
     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/10")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
-    (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
+    (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/22")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/23")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -10668,15 +10684,17 @@ test-convert-array-of-user-defined-types:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")"  "F - test-convert-array-of-user-defined-types/10")
-    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/11")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
+    (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-array-of-user-defined-types/12")
+    (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-array-of-user-defined-types/13")
+    (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/14")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/15")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/16")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/17")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/18")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/19")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/20")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/21")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/22")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -29476,17 +29494,25 @@ translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), st
     51/push-ecx
     52/push-edx
     53/push-ebx
-    #
-    (emit-indent *(ebp+8) *Curr-block-depth)
-    (write-buffered *(ebp+8) "8d/copy-address *(")
-    # TODO: ensure inouts[0] is in a register and not dereferenced
-$translate-mu-index-stmt-with-array-in-register:emit-base:
     # ecx = stmt
     8b/-> *(ebp+0xc) 1/r32/ecx
     # var base/ebx: (addr var) = inouts[0]
     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
     89/<- %ebx 0/r32/eax
+    # emit null check
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "81 7/subop/compare %")
+    (lookup *(ebx+0x18) *(ebx+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-index-base-address/disp32\n")
+    #
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "8d/copy-address *(")
+    # TODO: ensure inouts[0] is in a register and not dereferenced
+$translate-mu-index-stmt-with-array-in-register:emit-base:
     # print base->register " + "
     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
     (write-buffered *(ebp+8) %eax)