about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-08-22 22:10:02 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-08-22 22:10:02 -0700
commit791a71e27eb7a4c906c4454b6a49643a98662df6 (patch)
treea554b4a8b370f14e618e56f8229cad4951bb8f34
parentba4a3c5be70d473479e663be0400b798f88c113d (diff)
downloadmu-791a71e27eb7a4c906c4454b6a49643a98662df6.tar.gz
fix a long-standing bug in Mu's translator
While all test pass, this change is disquieting. When I first designed
Mu I deliberately chose to exclude literal strings from most primitive
instructions both for type-checking and to avoid silently passing
through strange constructions. Nobody really needs to add a string to a
number, and am I sure no SubX instruction will cause a memory safety
issue when passed a string literal instead of a number?

But clearly I have no tests encoding this desire. And any string literal
could be replaced by an integer literal containing the exact same value,
so what are we protecting against anyway.

Let me fix the bug for now. If I run into problems I'll come back and do
this right.
-rwxr-xr-xlinux/mubin609389 -> 610870 bytes
-rw-r--r--linux/mu.subx47
2 files changed, 47 insertions, 0 deletions
diff --git a/linux/mu b/linux/mu
index ff127f40..d7bd4eb9 100755
--- a/linux/mu
+++ b/linux/mu
Binary files differdiff --git a/linux/mu.subx b/linux/mu.subx
index 4f69e96a..16097264 100644
--- a/linux/mu.subx
+++ b/linux/mu.subx
@@ -7927,6 +7927,50 @@ test-copy-null-value-to-address:
     5d/pop-to-ebp
     c3/return
 
+test-copy-string-literal:
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (clear-stream $_test-input-buffered-file->buffer)
+    (clear-stream _test-output-stream)
+    (clear-stream $_test-output-buffered-file->buffer)
+    #
+    (write _test-input-stream "fn foo {\n")
+    (write _test-input-stream "  var y/ecx: (addr array byte) <- copy \"a\"\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
+    (flush _test-output-buffered-file)
+    # no errors
+#?     # dump _test-output-stream {{{
+#?     (write 2 "^")
+#?     (write-stream 2 _test-output-stream)
+#?     (write 2 "$\n")
+#?     (rewind-stream _test-output-stream)
+#?     # }}}
+    # check output
+    (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-string-literal/0")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-string-literal/1")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-string-literal/2")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-string-literal/3")
+    (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-string-literal/4")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-string-literal/5")
+    (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-copy-string-literal/6")
+    (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx \"a\"/imm32"  "F - test-copy-string-literal/7")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-copy-string-literal/8")
+    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-string-literal/9")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-string-literal/10")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-string-literal/11")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-string-literal/12")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-string-literal/13")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-string-literal/14")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 test-copy-invalid-value-to-offset:
     # . prologue
     55/push-ebp
@@ -36256,6 +36300,9 @@ type-category:  # a: (addr type-tree) -> result/eax: int
     # var lit?/ecx: boolean = literal-type?(a)
     (simple-mu-type? *(ebp+8) 0)  # literal => eax
     89/<- %ecx 0/r32/eax
+    # lit? |= string-literal?(a)
+    (simple-mu-type? *(ebp+8) 0x10)  # literal-string => eax
+    09/or %ecx 0/r32/eax
     # var float?/eax: int = float?(a)
     (simple-mu-type? *(ebp+8) 0xf)  # => eax
     # set bits for lit? and float?