From: Tim Wickberg <tim@schedmd.com>
Date: Tue Nov 28 17:31:52 2023 -0700
Subject: [PATCH 4/29]Use safe_xcalloc().
Patch-mainline: Upstream
Git-repo: https://github.com/SchedMD/slurm
Git-commit: 0e753de08d3e65ceb264637ed821cc9c39587dfc
References: bsc#1218046, bsc#1218050, bsc#1218051, bsc#1218053
Signed-off-by: Egbert Eich <eich@suse.de>

---
 src/common/pack.c    | 35 +++++++++++++++++++++++++----------
 src/common/pack.h    | 17 +++++++++++++++++
 src/common/xmalloc.c | 28 ++++++++++++++++++++++++++++
 src/common/xmalloc.h |  5 +++++
 4 files changed, 75 insertions(+), 10 deletions(-)

diff --git a/src/common/pack.c b/src/common/pack.c
index ebb7287fdf..4e8af68477 100644
--- a/src/common/pack.c
+++ b/src/common/pack.c
@@ -397,12 +397,15 @@ int unpack16_array(uint16_t ** valp, uint32_t * size_val, Buf buffer)
 	if (unpack32(size_val, buffer))
 		return SLURM_ERROR;
 
-	*valp = xmalloc_nz((*size_val) * sizeof(uint16_t));
+	safe_xcalloc(*valp, *size_val, sizeof(uint16_t));
 	for (i = 0; i < *size_val; i++) {
 		if (unpack16((*valp) + i, buffer))
-			return SLURM_ERROR;
+			goto unpack_error;
 	}
 	return SLURM_SUCCESS;
+
+unpack_error:
+	return SLURM_ERROR;
 }
 
 /* Given a *uint32_t, it will pack an array of size_val */
@@ -426,12 +429,15 @@ int unpack32_array(uint32_t ** valp, uint32_t * size_val, Buf buffer)
 	if (unpack32(size_val, buffer))
 		return SLURM_ERROR;
 
-	*valp = xmalloc_nz((*size_val) * sizeof(uint32_t));
+	safe_xcalloc(*valp, *size_val, sizeof(uint32_t));
 	for (i = 0; i < *size_val; i++) {
 		if (unpack32((*valp) + i, buffer))
-			return SLURM_ERROR;
+			goto unpack_error;
 	}
 	return SLURM_SUCCESS;
+
+unpack_error:
+	return SLURM_ERROR;
 }
 
 /* Given a *uint64_t, it will pack an array of size_val */
@@ -468,12 +474,15 @@ int unpack64_array(uint64_t ** valp, uint32_t * size_val, Buf buffer)
 	if (unpack32(size_val, buffer))
 		return SLURM_ERROR;
 
-	*valp = xmalloc_nz((*size_val) * sizeof(uint64_t));
+	safe_xcalloc(*valp, *size_val, sizeof(uint64_t));
 	for (i = 0; i < *size_val; i++) {
 		if (unpack64((*valp) + i, buffer))
-			return SLURM_ERROR;
+			goto unpack_error;
 	}
 	return SLURM_SUCCESS;
+
+unpack_error:
+	return SLURM_ERROR;
 }
 
 /* Unpack an array of 64bit values as if they were 32bit
@@ -512,12 +521,15 @@ int unpackdouble_array(double **valp, uint32_t* size_val, Buf buffer)
 	if (unpack32(size_val, buffer))
 		return SLURM_ERROR;
 
-	*valp = xmalloc_nz((*size_val) * sizeof(double));
+	safe_xcalloc(*valp, *size_val, sizeof(double));
 	for (i = 0; i < *size_val; i++) {
 		if (unpackdouble((*valp) + i, buffer))
-			return SLURM_ERROR;
+			goto unpack_error;
 	}
 	return SLURM_SUCCESS;
+
+unpack_error:
+	return SLURM_ERROR;
 }
 
 void packlongdouble_array(long double *valp, uint32_t size_val, Buf buffer)
@@ -538,12 +550,15 @@ int unpacklongdouble_array(long double **valp, uint32_t* size_val, Buf buffer)
 	if (unpack32(size_val, buffer))
 		return SLURM_ERROR;
 
-	*valp = xmalloc_nz((*size_val) * sizeof(long double));
+	safe_xcalloc(*valp, *size_val, sizeof(long double));
 	for (i = 0; i < *size_val; i++) {
 		if (unpacklongdouble((*valp) + i, buffer))
-			return SLURM_ERROR;
+			goto unpack_error;
 	}
 	return SLURM_SUCCESS;
+
+unpack_error:
+	return SLURM_ERROR;
 }
 
 
diff --git a/src/common/pack.h b/src/common/pack.h
index 4f0f0312ce..d8e062cc7c 100644
--- a/src/common/pack.h
+++ b/src/common/pack.h
@@ -355,6 +355,23 @@ int	unpackmem_array(char *valp, uint32_t size_valp, Buf buffer);
 		goto unpack_error;			\
 } while (0)
 
+#define safe_xcalloc(p, cnt, sz) do {                   \
+        size_t _cnt = cnt;                              \
+        size_t _sz = sz;                                \
+        if (!_cnt || !_sz)                              \
+                p = NULL;                               \
+        else if (!(p = try_xcalloc(_cnt, _sz)))         \
+                goto unpack_error;                      \
+} while (0)
+
+#define safe_xmalloc(p, sz) do {                        \
+        size_t _sz = sz;                                \
+        if (!_sz)                                       \
+                p = NULL;                               \
+        else if (!(p = try_xmalloc(_sz)))               \
+                goto unpack_error;                      \
+} while (0)
+
 #define FREE_NULL_BUFFER(_X)		\
 	do {				\
 		if (_X) free_buf (_X);	\
diff --git a/src/common/xmalloc.c b/src/common/xmalloc.c
index 8dcadb9646..f758fb2aad 100644
--- a/src/common/xmalloc.c
+++ b/src/common/xmalloc.c
@@ -120,6 +120,34 @@ void *slurm_try_xmalloc(size_t size, const char *file, int line,
 	return new;
 }
 
+void *slurm_try_xcalloc(size_t count, size_t size, const char *file, int line,
+                        const char *func)
+{
+	void *new;
+	size_t *p;
+	size_t count_size;
+	size_t total_size;
+
+	if (!size || !count)
+		return NULL;
+
+	if ((count != 1) && (count > SIZE_MAX / size / 4))
+	        return NULL;
+
+	count_size = count * size;
+	total_size = count_size + 2 * sizeof(size_t);
+
+	p = calloc(1, total_size);
+	if (!p) {
+		return NULL;
+	}
+	p[0] = XMALLOC_MAGIC;	/* add "secret" magic cookie */
+	p[1] = count_size;	/* store size in buffer */
+
+	new = &p[2];
+	return new;
+}
+
 /*
  * "Safe" version of realloc().  Args are different: pass in a pointer to
  * the object to be realloced instead of the object itself.
diff --git a/src/common/xmalloc.h b/src/common/xmalloc.h
index 00f4c75335..9dcca8dc25 100644
--- a/src/common/xmalloc.h
+++ b/src/common/xmalloc.h
@@ -90,6 +90,9 @@
 #define try_xmalloc(__sz) \
 	slurm_try_xmalloc((uint64_t) __sz, __FILE__, __LINE__, __func__)
 
+#define try_xcalloc(__cnt, __sz) \
+        slurm_try_xcalloc(__cnt, (uint64_t) __sz, __FILE__, __LINE__, __func__)
+
 #define xfree(__p) \
 	slurm_xfree((void **)&(__p), __FILE__, __LINE__, __func__)
 
@@ -112,6 +115,8 @@
 
 void *slurm_xmalloc(uint64_t, bool, const char *, int, const char *);
 void *slurm_try_xmalloc(size_t , const char *, int , const char *);
+void *slurm_try_xcalloc(size_t count, size_t size, const char *file, int line,
+                        const char *func);
 void slurm_xfree(void **, const char *, int, const char *);
 void slurm_xfree_array(void ***array);
 void *slurm_xrealloc(void **, size_t, bool, const char *, int, const char *);
