From 973d90d7b1c802ead677da85a262f080444baa41 Mon Sep 17 00:00:00 2001 From: kalsprite Date: Tue, 11 Aug 2026 21:31:36 -0700 Subject: [PATCH] enforce matrix size limits on mul; overflow dims --- src/check_expr.cpp | 16 +++++++++++++++- src/check_type.cpp | 17 ++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2ca6e6df4..888c93e3d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4268,8 +4268,22 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand x->type = y->type; } } else { + // the result takes its rows from one operand and its columns from the other, + // so it can be larger than either. Each dimension is at least + // MATRIX_ELEMENT_COUNT_MIN, so testing them first keeps the product in range. + i64 row_count = xt->Matrix.row_count; + i64 column_count = yt->Matrix.column_count; + if (row_count > MATRIX_ELEMENT_COUNT_MAX || + column_count > MATRIX_ELEMENT_COUNT_MAX || + row_count*column_count > MATRIX_ELEMENT_COUNT_MAX) { + error(x->expr, "Matrix multiplication result exceeds the maximum matrix element count, got %lld, expected a maximum of %d", cast(long long)(row_count*column_count), MATRIX_ELEMENT_COUNT_MAX); + x->mode = Addressing_Invalid; + x->type = t_invalid; + return; + } + bool is_row_major = xt->Matrix.is_row_major && yt->Matrix.is_row_major; - x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count, nullptr, nullptr, is_row_major); + x->type = alloc_type_matrix(xt->Matrix.elem, row_count, column_count, nullptr, nullptr, is_row_major); } goto matrix_success; } else if (yt->kind == Type_Array) { diff --git a/src/check_type.cpp b/src/check_type.cpp index b56acc276..06419f5fc 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -3131,9 +3131,20 @@ gb_internal void check_matrix_type(CheckerContext *ctx, Type **type, Ast *node) } } - if ((generic_row == nullptr && generic_column == nullptr) && row_count*column_count > MATRIX_ELEMENT_COUNT_MAX) { - i64 element_count = row_count*column_count; - error(node, "Matrix types are limited to a maximum of %d elements, got %lld", MATRIX_ELEMENT_COUNT_MAX, cast(long long)element_count); + if (generic_row == nullptr && generic_column == nullptr) { + // row_count*column_count can overflow and wrap back under the limit, so test the + // dimensions first; each is at least MATRIX_ELEMENT_COUNT_MIN. Either one exceeding + // the maximum means the product does too + if (row_count > MATRIX_ELEMENT_COUNT_MAX || column_count > MATRIX_ELEMENT_COUNT_MAX || + row_count*column_count > MATRIX_ELEMENT_COUNT_MAX) { + // the element count is only printable when the multiply cannot overflow, which is + // exactly the case the dimension test above catches + if (row_count != 0 && column_count > I64_MAX/row_count) { + error(node, "Matrix types are limited to a maximum of %d elements, got %lld by %lld", MATRIX_ELEMENT_COUNT_MAX, cast(long long)row_count, cast(long long)column_count); + } else { + error(node, "Matrix types are limited to a maximum of %d elements, got %lld by %lld (%lld elements)", MATRIX_ELEMENT_COUNT_MAX, cast(long long)row_count, cast(long long)column_count, cast(long long)(row_count*column_count)); + } + } }