Skip to content

Commit 3f07d1c

Browse files
committed
Fix No index OOB check for [:^n] #2123
1 parent 125436d commit 3f07d1c

File tree

3 files changed

+192
-2
lines changed

3 files changed

+192
-2
lines changed

releasenotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- Assert triggered when casting from `int[2]` to `uint[2]` #2115
1010
- Assert when a macro with compile time value is discarded, e.g. `foo();` where `foo()` returns an untyped list. #2117
1111
- Fix stringify for compound initializers #2120.
12+
- Fix No index OOB check for `[:^n]` #2123
1213

1314
### Stdlib changes
1415
- Added `String.quick_ztr` and `String.is_zstr`

src/compiler/llvm_codegen_expr.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,11 +2704,15 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
27042704
// This will trap any bad negative index, so we're fine.
27052705
if (safe_mode_enabled())
27062706
{
2707+
BEValue excess;
27072708
if (is_len_range)
27082709
{
2710+
llvm_emit_int_comp(c, &excess, &start_index, &end_index, BINARYOP_GT);
2711+
BEValue actual_end_len = end_index;
2712+
actual_end_len.value = llvm_emit_sub_int(c, end_index.type, end_index.value, start_index.value, slice->span);
2713+
llvm_emit_panic_if_true(c, &excess, "Negative slice length", slice->span, "Negative value (%d) given for slice length.", &actual_end_len, NULL);
27092714
if (len.value)
27102715
{
2711-
BEValue excess;
27122716
llvm_emit_int_comp(c, &excess, &len, &end_index, BINARYOP_LT);
27132717
BEValue actual_end_index = end_index;
27142718
actual_end_index.value = llvm_emit_sub_int(c, end_index.type, end_index.value, llvm_const_int(c, type_isz, 1), slice->span);
@@ -2717,7 +2721,6 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
27172721
}
27182722
else
27192723
{
2720-
BEValue excess;
27212724
llvm_emit_int_comp(c, &excess, &start_index, &end_index, BINARYOP_GT);
27222725
llvm_emit_panic_if_true(c, &excess, "Negative size", slice->span, "Negative size (start %d is less than end %d)", &start_index, &end_index);
27232726

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// #target: macos-x64
2+
// #safe: yes
3+
module test;
4+
fn int main()
5+
{
6+
String x = "ABCD";
7+
int z = 5;
8+
String y = x[1:^8];
9+
x[0:^z];
10+
return 0;
11+
}
12+
13+
/* #expect: test.ll
14+
15+
define i32 @main() #0 {
16+
entry:
17+
%x = alloca %"char[]", align 8
18+
%z = alloca i32, align 4
19+
%y = alloca %"char[]", align 8
20+
%taddr = alloca i64, align 8
21+
%taddr1 = alloca i64, align 8
22+
%varargslots = alloca [2 x %any], align 16
23+
%indirectarg = alloca %"any[]", align 8
24+
%taddr5 = alloca i64, align 8
25+
%varargslots6 = alloca [1 x %any], align 16
26+
%indirectarg8 = alloca %"any[]", align 8
27+
%taddr12 = alloca i64, align 8
28+
%taddr13 = alloca i64, align 8
29+
%varargslots14 = alloca [2 x %any], align 16
30+
%indirectarg17 = alloca %"any[]", align 8
31+
%taddr22 = alloca i64, align 8
32+
%taddr23 = alloca i64, align 8
33+
%varargslots24 = alloca [2 x %any], align 16
34+
%indirectarg27 = alloca %"any[]", align 8
35+
%taddr34 = alloca i64, align 8
36+
%varargslots35 = alloca [1 x %any], align 16
37+
%indirectarg37 = alloca %"any[]", align 8
38+
%taddr42 = alloca i64, align 8
39+
%taddr43 = alloca i64, align 8
40+
%varargslots44 = alloca [2 x %any], align 16
41+
%indirectarg47 = alloca %"any[]", align 8
42+
store %"char[]" { ptr @.str, i64 4 }, ptr %x, align 8
43+
store i32 5, ptr %z, align 4
44+
%0 = load %"char[]", ptr %x, align 8
45+
%1 = extractvalue %"char[]" %0, 0
46+
%2 = extractvalue %"char[]" %0, 1
47+
%gt = icmp sgt i64 1, %2
48+
%3 = call i1 @llvm.expect.i1(i1 %gt, i1 false)
49+
br i1 %3, label %panic, label %checkok
50+
51+
checkok: ; preds = %entry
52+
%sub = sub i64 %2, 8
53+
%add = add i64 1, %sub
54+
%gt2 = icmp sgt i64 1, %add
55+
%sub3 = sub i64 %add, 1
56+
%4 = call i1 @llvm.expect.i1(i1 %gt2, i1 false)
57+
br i1 %4, label %panic4, label %checkok9
58+
59+
checkok9: ; preds = %checkok
60+
%lt = icmp slt i64 %2, %add
61+
%sub10 = sub i64 %add, 1
62+
%5 = call i1 @llvm.expect.i1(i1 %lt, i1 false)
63+
br i1 %5, label %panic11, label %checkok18
64+
65+
checkok18: ; preds = %checkok9
66+
%size = sub i64 %add, 1
67+
%ptradd19 = getelementptr inbounds i8, ptr %1, i64 1
68+
%6 = insertvalue %"char[]" undef, ptr %ptradd19, 0
69+
%7 = insertvalue %"char[]" %6, i64 %size, 1
70+
store %"char[]" %7, ptr %y, align 8
71+
%8 = load %"char[]", ptr %x, align 8
72+
%9 = extractvalue %"char[]" %8, 0
73+
%10 = extractvalue %"char[]" %8, 1
74+
%gt20 = icmp sgt i64 0, %10
75+
%11 = call i1 @llvm.expect.i1(i1 %gt20, i1 false)
76+
br i1 %11, label %panic21, label %checkok28
77+
78+
checkok28: ; preds = %checkok18
79+
%12 = load i32, ptr %z, align 4
80+
%sext = sext i32 %12 to i64
81+
%sub29 = sub i64 %10, %sext
82+
%add30 = add i64 0, %sub29
83+
%gt31 = icmp sgt i64 0, %add30
84+
%sub32 = sub i64 %add30, 0
85+
%13 = call i1 @llvm.expect.i1(i1 %gt31, i1 false)
86+
br i1 %13, label %panic33, label %checkok38
87+
88+
checkok38: ; preds = %checkok28
89+
%lt39 = icmp slt i64 %10, %add30
90+
%sub40 = sub i64 %add30, 1
91+
%14 = call i1 @llvm.expect.i1(i1 %lt39, i1 false)
92+
br i1 %14, label %panic41, label %checkok48
93+
94+
checkok48: ; preds = %checkok38
95+
%size49 = sub i64 %add30, 0
96+
%15 = insertvalue %"char[]" undef, ptr %9, 0
97+
%16 = insertvalue %"char[]" %15, i64 %size49, 1
98+
ret i32 0
99+
100+
panic: ; preds = %entry
101+
store i64 %2, ptr %taddr, align 8
102+
%17 = insertvalue %any undef, ptr %taddr, 0
103+
%18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.long" to i64), 1
104+
store i64 1, ptr %taddr1, align 8
105+
%19 = insertvalue %any undef, ptr %taddr1, 0
106+
%20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.long" to i64), 1
107+
store %any %18, ptr %varargslots, align 16
108+
%ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16
109+
store %any %20, ptr %ptradd, align 16
110+
%21 = insertvalue %"any[]" undef, ptr %varargslots, 0
111+
%"$$temp" = insertvalue %"any[]" %21, i64 2, 1
112+
store %"any[]" %"$$temp", ptr %indirectarg, align 8
113+
call void @std.core.builtin.panicf(ptr @.panic_msg, i64 61, ptr @.file, i64 19, ptr @.func, i64 4, i32 6, ptr byval(%"any[]") align 8 %indirectarg) #2
114+
unreachable
115+
116+
panic4: ; preds = %checkok
117+
store i64 %sub3, ptr %taddr5, align 8
118+
%22 = insertvalue %any undef, ptr %taddr5, 0
119+
%23 = insertvalue %any %22, i64 ptrtoint (ptr @"$ct.long" to i64), 1
120+
store %any %23, ptr %varargslots6, align 16
121+
%24 = insertvalue %"any[]" undef, ptr %varargslots6, 0
122+
%"$$temp7" = insertvalue %"any[]" %24, i64 1, 1
123+
store %"any[]" %"$$temp7", ptr %indirectarg8, align 8
124+
call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 43, ptr @.file, i64 19, ptr @.func, i64 4, i32 6, ptr byval(%"any[]") align 8 %indirectarg8) #2
125+
unreachable
126+
127+
panic11: ; preds = %checkok9
128+
store i64 %sub10, ptr %taddr12, align 8
129+
%25 = insertvalue %any undef, ptr %taddr12, 0
130+
%26 = insertvalue %any %25, i64 ptrtoint (ptr @"$ct.long" to i64), 1
131+
store i64 %2, ptr %taddr13, align 8
132+
%27 = insertvalue %any undef, ptr %taddr13, 0
133+
%28 = insertvalue %any %27, i64 ptrtoint (ptr @"$ct.long" to i64), 1
134+
store %any %26, ptr %varargslots14, align 16
135+
%ptradd15 = getelementptr inbounds i8, ptr %varargslots14, i64 16
136+
store %any %28, ptr %ptradd15, align 16
137+
%29 = insertvalue %"any[]" undef, ptr %varargslots14, 0
138+
%"$$temp16" = insertvalue %"any[]" %29, i64 2, 1
139+
store %"any[]" %"$$temp16", ptr %indirectarg17, align 8
140+
call void @std.core.builtin.panicf(ptr @.panic_msg.2, i64 60, ptr @.file, i64 19, ptr @.func, i64 4, i32 6, ptr byval(%"any[]") align 8 %indirectarg17) #2
141+
unreachable
142+
143+
panic21: ; preds = %checkok18
144+
store i64 %10, ptr %taddr22, align 8
145+
%30 = insertvalue %any undef, ptr %taddr22, 0
146+
%31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.long" to i64), 1
147+
store i64 0, ptr %taddr23, align 8
148+
%32 = insertvalue %any undef, ptr %taddr23, 0
149+
%33 = insertvalue %any %32, i64 ptrtoint (ptr @"$ct.long" to i64), 1
150+
store %any %31, ptr %varargslots24, align 16
151+
%ptradd25 = getelementptr inbounds i8, ptr %varargslots24, i64 16
152+
store %any %33, ptr %ptradd25, align 16
153+
%34 = insertvalue %"any[]" undef, ptr %varargslots24, 0
154+
%"$$temp26" = insertvalue %"any[]" %34, i64 2, 1
155+
store %"any[]" %"$$temp26", ptr %indirectarg27, align 8
156+
call void @std.core.builtin.panicf(ptr @.panic_msg, i64 61, ptr @.file, i64 19, ptr @.func, i64 4, i32 7, ptr byval(%"any[]") align 8 %indirectarg27) #2
157+
unreachable
158+
159+
panic33: ; preds = %checkok28
160+
store i64 %sub32, ptr %taddr34, align 8
161+
%35 = insertvalue %any undef, ptr %taddr34, 0
162+
%36 = insertvalue %any %35, i64 ptrtoint (ptr @"$ct.long" to i64), 1
163+
store %any %36, ptr %varargslots35, align 16
164+
%37 = insertvalue %"any[]" undef, ptr %varargslots35, 0
165+
%"$$temp36" = insertvalue %"any[]" %37, i64 1, 1
166+
store %"any[]" %"$$temp36", ptr %indirectarg37, align 8
167+
call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 43, ptr @.file, i64 19, ptr @.func, i64 4, i32 7, ptr byval(%"any[]") align 8 %indirectarg37) #2
168+
unreachable
169+
170+
panic41: ; preds = %checkok38
171+
store i64 %sub40, ptr %taddr42, align 8
172+
%38 = insertvalue %any undef, ptr %taddr42, 0
173+
%39 = insertvalue %any %38, i64 ptrtoint (ptr @"$ct.long" to i64), 1
174+
store i64 %10, ptr %taddr43, align 8
175+
%40 = insertvalue %any undef, ptr %taddr43, 0
176+
%41 = insertvalue %any %40, i64 ptrtoint (ptr @"$ct.long" to i64), 1
177+
store %any %39, ptr %varargslots44, align 16
178+
%ptradd45 = getelementptr inbounds i8, ptr %varargslots44, i64 16
179+
store %any %41, ptr %ptradd45, align 16
180+
%42 = insertvalue %"any[]" undef, ptr %varargslots44, 0
181+
%"$$temp46" = insertvalue %"any[]" %42, i64 2, 1
182+
store %"any[]" %"$$temp46", ptr %indirectarg47, align 8
183+
call void @std.core.builtin.panicf(ptr @.panic_msg.2, i64 60, ptr @.file, i64 19, ptr @.func, i64 4, i32 7, ptr byval(%"any[]") align 8 %indirectarg47) #2
184+
unreachable
185+
}
186+

0 commit comments

Comments
 (0)