Skip to content

Commit 160367e

Browse files
committed
fix compile error for reading past end of pointer casted array
1 parent 6b6f2fc commit 160367e

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

src/ir.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19971,6 +19971,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1997119971
buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);
1997219972
if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
1997319973
return err;
19974+
buf_deinit(&buf);
1997419975
return ErrorNone;
1997519976
}
1997619977

@@ -19990,7 +19991,31 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1999019991
dst_size, buf_ptr(&pointee->type->name), src_size));
1999119992
return ErrorSemanticAnalyzeFail;
1999219993
}
19993-
case ConstPtrSpecialSubArray:
19994+
case ConstPtrSpecialSubArray: {
19995+
ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
19996+
assert(array_val->type->id == ZigTypeIdArray);
19997+
if (array_val->data.x_array.special != ConstArraySpecialNone)
19998+
zig_panic("TODO");
19999+
if (dst_size > src_size) {
20000+
size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
20001+
opt_ir_add_error_node(ira, codegen, source_node,
20002+
buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes",
20003+
dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
20004+
return ErrorSemanticAnalyzeFail;
20005+
}
20006+
size_t elem_size = src_size;
20007+
size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
20008+
Buf buf = BUF_INIT;
20009+
buf_resize(&buf, elem_count * elem_size);
20010+
for (size_t i = 0; i < elem_count; i += 1) {
20011+
ZigValue *elem_val = &array_val->data.x_array.data.s_none.elements[i];
20012+
buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
20013+
}
20014+
if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
20015+
return err;
20016+
buf_deinit(&buf);
20017+
return ErrorNone;
20018+
}
1999420019
case ConstPtrSpecialBaseArray: {
1999520020
ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1999620021
assert(array_val->type->id == ZigTypeIdArray);
@@ -20014,6 +20039,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
2001420039
}
2001520040
if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
2001620041
return err;
20042+
buf_deinit(&buf);
2001720043
return ErrorNone;
2001820044
}
2001920045
case ConstPtrSpecialBaseStruct:

test/compile_errors.zig

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,17 +1903,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
19031903
"tmp.zig:7:15: error: switch must handle all possibilities",
19041904
});
19051905

1906-
// TODO uncomment before merging branch
1907-
//cases.add("reading past end of pointer casted array",
1908-
// \\comptime {
1909-
// \\ const array: [4]u8 = "aoeu".*;
1910-
// \\ const sub_array = array[1..];
1911-
// \\ const int_ptr = @ptrCast(*const u24, sub_array);
1912-
// \\ const deref = int_ptr.*;
1913-
// \\}
1914-
//, &[_][]const u8{
1915-
// "tmp.zig:5:26: error: attempt to read 4 bytes from [4]u8 at index 1 which is 3 bytes",
1916-
//});
1906+
cases.add("reading past end of pointer casted array",
1907+
\\comptime {
1908+
\\ const array: [4]u8 = "aoeu".*;
1909+
\\ const sub_array = array[1..];
1910+
\\ const int_ptr = @ptrCast(*const u24, sub_array);
1911+
\\ const deref = int_ptr.*;
1912+
\\}
1913+
, &[_][]const u8{
1914+
"tmp.zig:5:26: error: attempt to read 4 bytes from [4]u8 at index 1 which is 3 bytes",
1915+
});
19171916

19181917
cases.add("error note for function parameter incompatibility",
19191918
\\fn do_the_thing(func: fn (arg: i32) void) void {}

0 commit comments

Comments
 (0)