feat(compiler): a slice index is checked against its length
A slice has carried { ptr, len, cap } since it existed and nothing ever read
the len: every index emitted a bare getelementptr. Running off the end of one
wrote into whatever the allocator had put next, and the program died somewhere
else entirely - a maroon-lake crash took a day to find because the stack named
a texture upload and the write was in a telemetry buffer five frames earlier.
Now each index loads the length and compares unsigned, which rejects a negative
index in the same instruction, and a failure aborts with the location the other
located errors use:
oob.ludic:9: index out of range: 7, len 3
`words` and the other raw buffers are unchanged - they are a bare malloc with no
length to check, which is the argument for moving off them.
The SPIR-V variants are regenerated in the same commit: shaders --check was
failing against the edited GLSL.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
f7f47152bd
commit
0998cb5a18
77 changed files with 803 additions and 696 deletions
|
|
@ -217,6 +217,7 @@ function emit_program() -> void {
|
|||
g_uses_loopback = false
|
||||
g_uses_expect = false
|
||||
g_uses_panic = false
|
||||
g_fprintf_declared = false
|
||||
g_uses_result = false
|
||||
g_uses_option = false
|
||||
g_uses_world_despawn = false # #84: set when a world_despawn call is emitted (below)
|
||||
|
|
@ -281,8 +282,13 @@ function emit_program() -> void {
|
|||
if g_uses_datert { emit_datetime_prelude() } # @lp_days_from_civil / @lp_civil_from_days conversions
|
||||
if g_uses_panic { # panic/assert: located abort to stderr
|
||||
emith("declare i32 @fprintf(ptr, ptr, ...)\n")
|
||||
g_fprintf_declared = true
|
||||
emith("@.fmt_panic = private unnamed_addr constant [6 x i8] c\"%s%s\\0A\\00\"\n")
|
||||
}
|
||||
if g_uses_bounds { # a slice index out of range: located abort
|
||||
if not g_fprintf_declared { emith("declare i32 @fprintf(ptr, ptr, ...)\n"); g_fprintf_declared = true }
|
||||
emith("@.fmt_bounds = private unnamed_addr constant [14 x i8] c\"%s%d, len %d\\0A\\00\"\n")
|
||||
}
|
||||
if g_uses_result { emith("%Result = type { i32, i32, ptr }\n") } # issue #46: ok/err/try value
|
||||
if g_uses_option { emith("%Option = type { i32, i32 }\n") } # issue #53: some/none value
|
||||
emit_cov_runtime() # issue #45: --coverage tables + exit dump
|
||||
|
|
@ -318,7 +324,7 @@ function emit_cov_runtime() -> void {
|
|||
let modec = emit_str_const("w")
|
||||
emith("@.cov_filefmt = private unnamed_addr constant [9 x i8] c\"FILE %s\\0A\\00\"\n")
|
||||
emith("@.cov_rowfmt = private unnamed_addr constant [7 x i8] c\"%d %d\\0A\\00\"\n")
|
||||
if not g_uses_panic { emith("declare i32 @fprintf(ptr, ptr, ...)\n") }
|
||||
if not g_fprintf_declared { emith("declare i32 @fprintf(ptr, ptr, ...)\n"); g_fprintf_declared = true }
|
||||
emith("declare i32 @atexit(ptr)\n")
|
||||
|
||||
# @cov_dump: open $LUDIC_COVERAGE (or "ludic.cov"), write a FILE header then one
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue