From b178ed36bdd841a76b6595edb77631886e099406 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= <tornaria@cmat.edu.uy>
Date: Mon, 3 Feb 2025 17:19:37 -0300
Subject: [PATCH] Fix overflows in `mzd_init()`

---
 m4ri/mmc.h | 4 ++++
 m4ri/mzd.c | 5 ++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/m4ri/mmc.h b/m4ri/mmc.h
index e6db4ca..3e97391 100644
--- a/m4ri/mmc.h
+++ b/m4ri/mmc.h
@@ -72,6 +72,10 @@ typedef struct _mm_block {
  * \return Pointer to allocated memory block.
  */
 static inline void *m4ri_mmc_calloc(size_t count, size_t size) {
+  if (size && count > SIZE_MAX/size) {
+      m4ri_die("m4ri_mmc_calloc: overflow in multiplication\n");
+      return NULL; /* unreachable */
+  }
   size_t total_size = count * size;
   void *ret         = m4ri_mmc_malloc(total_size);
   memset((char *)ret, 0, total_size);
diff --git a/m4ri/mzd.c b/m4ri/mzd.c
index ba04b7c..ac62c5c 100644
--- a/m4ri/mzd.c
+++ b/m4ri/mzd.c
@@ -144,13 +144,12 @@ mzd_t *mzd_init(rci_t r, rci_t c) {
   mzd_t *A = mzd_t_malloc();
   A->nrows         = r;
   A->ncols         = c;
-  A->width         = (c + m4ri_radix - 1) / m4ri_radix;
+  A->width         = c > 0 ? (c - 1) / m4ri_radix + 1 : 0;
   A->rowstride     = ((A->width & 1) == 0) ? A->width : A->width + 1;
   A->high_bitmask  = __M4RI_LEFT_BITMASK(c % m4ri_radix);
   A->flags         = (A->high_bitmask != m4ri_ffff) ? mzd_flag_nonzero_excess : 0;
   if (r && c) {
-    size_t block_words = r * A->rowstride;
-    A->data = m4ri_mmc_calloc(block_words, sizeof(word));
+    A->data = m4ri_mmc_calloc(r, sizeof(word) * A->rowstride);
   } else {
     A->data = NULL;
   }
