From e944df5cf7490d76a2253e48e086b64eb496a05b Mon Sep 17 00:00:00 2001
From: Tim Wickberg <tim@schedmd.com>
Date: Tue, 4 Sep 2018 18:49:22 -0600
Subject: [PATCH] Add xcalloc() macro and convert slurm_xmalloc into
 slurm_xcalloc() function.

Use this instead of handling the multiplication ourselves. This lets us
check for potential problems from integer overflow, and IMNSHO makes the
code look a lot tidier.

Rework xmalloc() and xmalloc_nz() macros in terms of slurm_xcalloc().

Bug 6310.
---
 src/common/xmalloc.c | 27 +++++++++++++++++++++------
 src/common/xmalloc.h |  9 ++++++---
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/src/common/xmalloc.c b/src/common/xmalloc.c
index 37bcbfa1aef..d32fd538346 100644
--- a/src/common/xmalloc.c
+++ b/src/common/xmalloc.c
@@ -43,6 +43,7 @@
 
 #include <errno.h>
 #include <pthread.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -71,16 +72,31 @@ static void malloc_assert_failed(char *, const char *, int,
  *   clear (IN) initialize to zero
  *   RETURN	pointer to allocate heap space
  */
-void *slurm_xmalloc(size_t size, bool clear,
+void *slurm_xcalloc(size_t count, size_t size, bool clear,
 		    const char *file, int line, const char *func)
 {
-	void *new;
+	size_t total_size;
 	size_t *p;
-	size_t total_size = size + 2 * sizeof(size_t);
 
-	if (size <= 0)
+	if (!size || !count)
 		return NULL;
 
+	/*
+	 * Detect overflow of the size calculation and abort().
+	 * Ensure there is sufficient space for the two header words used to
+	 * store the magic value and the allocation length by dividing by two,
+	 * and because on 32-bit systems, if a 2GB allocation request isn't
+	 * sufficient (which would attempt to allocate 2GB + 8Bytes),
+	 * then we're going to run into other problems anyways.
+	 * (And on 64-bit, if a 2EB + 16Bytes request isn't sufficient...)
+	 */
+	if ((count != 1) && (count > SIZE_MAX / size / 4)) {
+		log_oom(file, line, func);
+		abort();
+	}
+
+	total_size = count * size + 2 * sizeof(size_t);
+
 	if (clear)
 		p = calloc(1, total_size);
 	else
@@ -93,8 +109,7 @@ void *slurm_xmalloc(size_t size, bool clear,
 	p[0] = XMALLOC_MAGIC;	/* add "secret" magic cookie */
 	p[1] = size;		/* store size in buffer */
 
-	new = &p[2];
-	return new;
+	return &p[2];
 }
 
 /*
diff --git a/src/common/xmalloc.h b/src/common/xmalloc.h
index a4c96bd127e..89d4949b48d 100644
--- a/src/common/xmalloc.h
+++ b/src/common/xmalloc.h
@@ -71,11 +71,14 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
+#define xcalloc(__cnt, __sz) \
+	slurm_xcalloc(__cnt, __sz, true, __FILE__, __LINE__, __func__)
+
 #define xmalloc(__sz) \
-	slurm_xmalloc (__sz, true, __FILE__, __LINE__, __func__)
+	slurm_xcalloc(1, __sz, true, __FILE__, __LINE__, __func__)
 
 #define xmalloc_nz(__sz) \
-	slurm_xmalloc (__sz, false, __FILE__, __LINE__, __func__)
+	slurm_xcalloc(1, __sz, false, __FILE__, __LINE__, __func__)
 
 #define xfree(__p) \
 	slurm_xfree((void **)&(__p), __FILE__, __LINE__, __func__)
@@ -91,7 +94,7 @@
 #define xsize(__p) \
 	slurm_xsize((void *)__p, __FILE__, __LINE__, __func__)
 
-void *slurm_xmalloc(size_t, bool, const char *, int, const char *);
+void *slurm_xcalloc(size_t, size_t, bool, const char *, int, const char *);
 void slurm_xfree(void **, const char *, int, const char *);
 void *slurm_xrealloc(void **, size_t, bool, const char *, int, const char *);
 size_t slurm_xsize(void *, const char *, int, const char *);
-- 
GitLab