diff -r eb48f716b31c -r e10457d74fe1 src/ucx/allocator.c
--- a/src/ucx/allocator.c	Mon Feb 10 17:44:51 2025 +0100
+++ b/src/ucx/allocator.c	Sun Mar 02 18:10:52 2025 +0100
@@ -28,35 +28,33 @@
 
 #include "cx/allocator.h"
 
-__attribute__((__malloc__, __alloc_size__(2)))
+#include <errno.h>
+
 static void *cx_malloc_stdlib(
-        __attribute__((__unused__)) void *d,
+        cx_attr_unused void *d,
         size_t n
 ) {
     return malloc(n);
 }
 
-__attribute__((__warn_unused_result__, __alloc_size__(3)))
 static void *cx_realloc_stdlib(
-        __attribute__((__unused__)) void *d,
+        cx_attr_unused void *d,
         void *mem,
         size_t n
 ) {
     return realloc(mem, n);
 }
 
-__attribute__((__malloc__, __alloc_size__(2, 3)))
 static void *cx_calloc_stdlib(
-        __attribute__((__unused__)) void *d,
-        size_t nelem,
-        size_t n
+        cx_attr_unused void *d,
+        size_t nmemb,
+        size_t size
 ) {
-    return calloc(nelem, n);
+    return calloc(nmemb, size);
 }
 
-__attribute__((__nonnull__))
 static void cx_free_stdlib(
-        __attribute__((__unused__)) void *d,
+        cx_attr_unused void *d,
         void *mem
 ) {
     free(mem);
@@ -73,47 +71,96 @@
         &cx_default_allocator_class,
         NULL
 };
-CxAllocator *cxDefaultAllocator = &cx_default_allocator;
+const CxAllocator * const cxDefaultAllocator = &cx_default_allocator;
 
-
-int cx_reallocate(
+int cx_reallocate_(
         void **mem,
         size_t n
 ) {
     void *nmem = realloc(*mem, n);
     if (nmem == NULL) {
-        return 1;
+        return 1; // LCOV_EXCL_LINE
     } else {
         *mem = nmem;
         return 0;
     }
 }
 
+int cx_reallocatearray_(
+        void **mem,
+        size_t nmemb,
+        size_t size
+) {
+    size_t n;
+    if (cx_szmul(nmemb, size, &n)) {
+        errno = EOVERFLOW;
+        return 1;
+    } else {
+        void *nmem = realloc(*mem, n);
+        if (nmem == NULL) {
+            return 1; // LCOV_EXCL_LINE
+        } else {
+            *mem = nmem;
+            return 0;
+        }
+    }
+}
+
 // IMPLEMENTATION OF HIGH LEVEL API
 
 void *cxMalloc(
-        CxAllocator const *allocator,
+        const CxAllocator *allocator,
         size_t n
 ) {
     return allocator->cl->malloc(allocator->data, n);
 }
 
 void *cxRealloc(
-        CxAllocator const *allocator,
+        const CxAllocator *allocator,
         void *mem,
         size_t n
 ) {
     return allocator->cl->realloc(allocator->data, mem, n);
 }
 
-int cxReallocate(
-        CxAllocator const *allocator,
+void *cxReallocArray(
+        const CxAllocator *allocator,
+        void *mem,
+        size_t nmemb,
+        size_t size
+) {
+    size_t n;
+    if (cx_szmul(nmemb, size, &n)) {
+        errno = EOVERFLOW;
+        return NULL;
+    } else {
+        return allocator->cl->realloc(allocator->data, mem, n);
+    }
+}
+
+int cxReallocate_(
+        const CxAllocator *allocator,
         void **mem,
         size_t n
 ) {
     void *nmem = allocator->cl->realloc(allocator->data, *mem, n);
     if (nmem == NULL) {
-        return 1;
+        return 1; // LCOV_EXCL_LINE
+    } else {
+        *mem = nmem;
+        return 0;
+    }
+}
+
+int cxReallocateArray_(
+        const CxAllocator *allocator,
+        void **mem,
+        size_t nmemb,
+        size_t size
+) {
+    void *nmem = cxReallocArray(allocator, *mem, nmemb, size);
+    if (nmem == NULL) {
+        return 1; // LCOV_EXCL_LINE
     } else {
         *mem = nmem;
         return 0;
@@ -121,15 +168,15 @@
 }
 
 void *cxCalloc(
-        CxAllocator const *allocator,
-        size_t nelem,
-        size_t n
+        const CxAllocator *allocator,
+        size_t nmemb,
+        size_t size
 ) {
-    return allocator->cl->calloc(allocator->data, nelem, n);
+    return allocator->cl->calloc(allocator->data, nmemb, size);
 }
 
 void cxFree(
-        CxAllocator const *allocator,
+        const CxAllocator *allocator,
         void *mem
 ) {
     allocator->cl->free(allocator->data, mem);