harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

commit fc7c103e72f5358142ed8a0492f06a74447fcdcf
parent 10543441a8d95e78299fbc77ceb56fd9b61d0baf
Author: Sebastian <sebastian@sebsite.pw>
Date:   Tue, 17 Jan 2023 01:04:37 -0500

check: fix NULL-dereference bugs

type_dereference returns NULL if the pointer is nullable. Some parts of
check didn't properly test for this, resulting in a segfault when a
nullable pointer was used. In particular, append/insert and delete
expressions. Furthermore, type_dereference was used on the type hint of
an object allocation expression, which was unnecessary and was also
susceptible to the segfault.

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Msrc/check.c | 25++++++++++++++++++++++---
Mtests/19-append.ha | 5+++++
2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -354,7 +354,7 @@ check_expr_alloc_init(struct context *ctx, "Cannot infer expandable array length without type hint"); return; } - const struct type *htype = type_dealias(type_dereference(inithint)); + const struct type *htype = type_dealias(inithint); if (htype->storage != STORAGE_ARRAY) { error(ctx, aexpr->loc, expr, "Cannot assign expandable array from non-array type"); @@ -522,7 +522,14 @@ check_expr_append_insert(struct context *ctx, default: abort(); // Invariant } - sltype = type_dealias(type_dereference(sltypename)); + sltype = type_dereference(sltypename); + if (!sltype) { + error(ctx, aexpr->access.tuple->loc, expr, + "Cannot dereference nullable pointer for %s expression", + exprtype_name); + return; + } + sltype = type_dealias(sltype); if (sltype->storage != STORAGE_SLICE) { char *typename = gen_typename(sltypename); @@ -556,6 +563,12 @@ check_expr_append_insert(struct context *ctx, check_expression(ctx, aexpr->append.value, expr->append.value, sltype); const struct type *valtype = type_dereference(expr->append.value->result); + if (!valtype) { + error(ctx, aexpr->loc, expr, + "Cannot dereference nullable pointer for %s expression", + exprtype_name); + return; + } valtype = type_dealias(valtype); if (aexpr->append.length) { if (valtype->storage != STORAGE_ARRAY @@ -1832,7 +1845,13 @@ check_expr_delete(struct context *ctx, "Deleted expression must be slicing or indexing expression"); return; } - otype = type_dealias(type_dereference(otype)); + otype = type_dereference(otype); + if (!otype) { + error(ctx, aexpr->loc, expr, + "Cannot dereference nullable pointer for delete expression"); + return; + } + otype = type_dealias(otype); if (otype->storage != STORAGE_SLICE) { error(ctx, aexpr->delete.expr->loc, expr, "delete must operate on a slice"); diff --git a/tests/19-append.ha b/tests/19-append.ha @@ -95,6 +95,11 @@ fn reject() void = { let x: []u8 = [0u8]; append(x, [42], 3); ") as exited != EXIT_SUCCESS); // must be an expandable array + assert(compile(" + let x: []u8 = [0u8]; + let x: nullable *[]u8 = &x; + append(x, 42); + ") as exited != EXIT_SUCCESS); // object member type is nullable pointer }; export fn main() void = {