From 7ba0d89c9f9710bb550201436840079fb71b18be Mon Sep 17 00:00:00 2001
From: Eugene Syromiatnikov <evgsyr@gmail.com>
Date: Thu, 24 Aug 2017 17:36:08 +0000
Subject: [PATCH] xstrdup, xtrndup: allow NULL argument

Accept NULL argument in xstrdup and xtrndup functions to allow use
of "xstrdup(str)" instead of "str ? xstrdup(str) : NULL".

* xmalloc.c (xstrdup, xstrndup): Handle NULL argument.
* xmalloc.h: Add comment regarding this deviation from the behaviour
of the POSIX counterparts of these functions.
---
 xmalloc.c | 6 ++++++
 xmalloc.h | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/xmalloc.c b/xmalloc.c
index 45ff57b1..c2c50f8c 100644
--- a/xmalloc.c
+++ b/xmalloc.c
@@ -91,6 +91,9 @@ xreallocarray(void *ptr, size_t nmemb, size_t size)
 char *
 xstrdup(const char *str)
 {
+	if (!str)
+		return NULL;
+
 	char *p = strdup(str);
 
 	if (!p)
@@ -104,6 +107,9 @@ xstrndup(const char *str, size_t n)
 {
 	char *p;
 
+	if (!str)
+		return NULL;
+
 #ifdef HAVE_STRNDUP
 	p = strndup(str, n);
 #else
diff --git a/xmalloc.h b/xmalloc.h
index ae0501dc..d1feeb91 100644
--- a/xmalloc.h
+++ b/xmalloc.h
@@ -41,6 +41,13 @@ void *xcalloc(size_t nmemb, size_t size)
 void *xmalloc(size_t size) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1));
 void *xreallocarray(void *ptr, size_t nmemb, size_t size)
 	ATTRIBUTE_ALLOC_SIZE((2, 3));
+
+/*
+ * Note that the following two functions return NULL when NULL is specified
+ * and not when allocation is failed, since, as the "x" prefix implies,
+ * the allocation failure leads to program termination, so we may re-purpose
+ * this return value and simplify the idiom "str ? xstrdup(str) : NULL".
+ */
 char *xstrdup(const char *str) ATTRIBUTE_MALLOC;
 char *xstrndup(const char *str, size_t n) ATTRIBUTE_MALLOC;
 
-- 
2.40.0