about summary refs log tree commit diff stats
path: root/LICENSE
blob: 67e22c37c3a994e66539612cb02de910eca91baa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
MIT/X Consortium License

(C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
(C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the 
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software. 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
DEALINGS IN THE SOFTWARE.
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# Helper to check an array's bounds, and to abort if they're violated.
# Really only intended to be called from code generated by mu.subx.

== code

__check-mu-array-bounds:  # index: int, elem-size: int, arr-size: int, function-name: (addr array byte), array-name: (addr array byte)
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    50/push-eax
    51/push-ecx
    52/push-edx
    # . not bothering saving ebx; it's only clobbered if we're going to abort
    # ecx = arr-size
    8b/-> *(ebp+0x10) 1/r32/ecx
    # var overflow/edx: int = 0
    ba/copy-to-edx 0/imm32
    # var offset/eax: int = index * elem-size
    8b/-> *(ebp+8) 0/r32/eax
    f7 4/subop/multiply-eax-with *(ebp+0xc)
    # check for overflow
    81 7/subop/compare %edx 0/imm32
    0f 85/jump-if-!= __check-mu-array-bounds:overflow/disp32
    # check bounds
    39/compare %eax 1/r32/ecx
    0f 82/jump-if-unsigned< $__check-mu-array-bounds:end/disp32  # negative index should always abort
    # abort if necessary
    (write-buffered Stderr "fn ")
    (write-buffered Stderr *(ebp+0x14))
    (write-buffered Stderr ": offset ")
    (write-int32-hex-buffered Stderr %eax)
    (write-buffered Stderr " is too large for array '")
    (write-buffered Stderr *(ebp+0x18))
    (write-buffered Stderr "'\n")
    (flush Stderr)
    # exit(1)
    bb/copy-to-ebx 1/imm32
    e8/call syscall_exit/disp32
    # never gets here
$__check-mu-array-bounds:end:
    # . restore registers
    5a/pop-to-edx
    59/pop-to-ecx
    58/pop-to-eax
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

__check-mu-array-bounds:overflow:
    # "fn " function-name ": offset to array '" array-name "' overflowed 32 bits\n"
    (write-buffered Stderr "fn ")
    (write-buffered Stderr *(ebp+0x14))
    (write-buffered Stderr ": offset to array '")
    (write-buffered Stderr *(ebp+0x18))
    (write-buffered Stderr "' overflowed 32 bits\n")
    (flush Stderr)
    # exit(1)
    bb/copy-to-ebx 1/imm32
    e8/call syscall_exit/disp32
    # never gets here

# potential alternative

#? __bounds-check:  # msg: (addr array byte)
#?   (write-buffered Stderr "abort: array bounds exceeded in fn ")
#?   8b/-> *(esp+4) 0/r32/eax  # we're going to abort, so just clobber away
#?   (write-buffered Stderr %eax)
#?   (write-buffered Stderr Newline)
#?   # exit(1)
#?   bb/copy-to-ebx 1/imm32
#?   e8/call syscall_exit/disp32

# to be called as follows:
#   var/reg <- index arr/rega: (addr array T), idx/regi: int
#     | if size-of(T) is 1, 2, 4 or 8
#         => # temporarily save array size to reg to check bounds
#            "8b/-> *" rega " " reg "/r32"
#            "c1/shift 5/subop/right %" reg " " log2(size-of(T)) "/imm32"
#            "3b/compare " reg "/r32 *" rega
#            "68/push \"" function "\"/imm32"  # pass function name to error message
#            "0f 8d/jump-if->= __bounds_check/disp32"
#            "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"