Skip to content

Commit

Permalink
Prevent implicit array casts to pointers with higher alignment. #1237
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Jul 14, 2024
1 parent 68fb916 commit 1a03e6b
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Max number of members in a struct is limited to 65535.
- The maximum number of parameters in a call is now 255, up from 127.
- Array comparison now uses built-in memcmp on LLVM to enable optimizations.
- Prevent implicit array casts to pointers with higher alignment #1237.

### Fixes
- Error with unsigned compare in `@ensure` when early returning 0 #1207.
Expand Down
1 change: 1 addition & 0 deletions src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2496,6 +2496,7 @@ typedef enum
TYPE_MISMATCH = 0,
TYPE_SAME = 1,
TYPE_SAME_INT_SIZE = 2,
TYPE_ALIGNMENT_INCREASE = 3,
TYPE_ERROR = -1,
} TypeCmpResult;

Expand Down
11 changes: 11 additions & 0 deletions src/compiler/sema_casts.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,17 @@ static bool rule_ptr_to_ptr(CastContext *cc, bool is_explicit, bool is_silent)
return true;
case TYPE_ERROR:
return false;
case TYPE_ALIGNMENT_INCREASE:
if (is_explicit) return false;
assert(!is_explicit);
RETURN_CAST_ERROR(cc->expr,
"Implicitly casting %s (alignment %d) to %s (alignment %d) is not permitted, "
"it would require an explicit cast. Before using an explicit cast, please make "
"sure you understand the ramifications as the explicit cast might crash your program if used incorrectly.",
type_quoted_error_string(type_no_optional(cc->expr->type)),
type_abi_alignment(type_get_indexed_type(cc->expr->type)),
type_quoted_error_string(cc->to),
type_abi_alignment(type_get_indexed_type(cc->to)));
case TYPE_MISMATCH:
case TYPE_SAME_INT_SIZE:
return sema_cast_error(cc, true, is_silent);
Expand Down
7 changes: 5 additions & 2 deletions src/compiler/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -1661,6 +1661,8 @@ TypeCmpResult type_is_pointer_equivalent(SemaContext *context, Type *to_pointer,

if (to_pointee->type_kind != from_pointee->type_kind)
{
TypeCmpResult res_current = TYPE_SAME;
if (type_abi_alignment(to_pointee) > type_abi_alignment(from_pointee)) res_current = TYPE_ALIGNMENT_INCREASE;
if (type_is_matching_int(to_pointee, from_pointee)) return TYPE_SAME_INT_SIZE;

if (type_is_any_arraylike(from_pointee))
Expand All @@ -1669,10 +1671,11 @@ TypeCmpResult type_is_pointer_equivalent(SemaContext *context, Type *to_pointer,
if (type_is_any_arraylike(to_pointee))
{
TypeCmpResult res = type_array_is_equivalent(context, to_pointee, from_pointee, flatten_distinct);
if (res != TYPE_MISMATCH) return res;
if (res != TYPE_MISMATCH) return res == TYPE_SAME ? res_current : res;
}
// A possible int[4]* -> int* decay?
return type_is_pointer_equivalent(context, type_get_ptr(from_pointee->array.base), to_pointer, flatten_distinct);
TypeCmpResult res = type_is_pointer_equivalent(context, type_get_ptr(from_pointee->array.base), to_pointer, flatten_distinct);
return res == TYPE_SAME ? res_current : res;
}
// Not arraylike and no array decay. Failure.
return TYPE_MISMATCH;
Expand Down
17 changes: 17 additions & 0 deletions test/test_suite/expressions/casts/cast_vector_fail.c3
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module foo;
import std;
fn void test(float[<4>]* x)
{}
fn void test2(float[4]* x)
{}

fn int main(String[] args)
{
float[4] a;
float[<4>] b;
test(&a); // #error: Implicitly casting
test(&b);
test2(&a);
test2(&b);
return 1;
}

0 comments on commit 1a03e6b

Please sign in to comment.