[PATCH] Fix string conversion

swen swen at linux.ibm.com
Mon Jan 28 13:46:41 UTC 2019


Please review and push if happy.

Thanks for your support in advance.

Cheers Swen
-------------- next part --------------
From 0f0756ea352b47074c9ae1a4d59d66cdf6bce8d0 Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 09:42:13 +0100
Subject: [PATCH 1/8] util: Add two wrapper for string to int conversion

Adding wrapper strtoull_err and strtoul_err to handle
error conditions of the conversion process.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 lib/util/util.c | 28 ++++++++++++++++++++++++++++
 lib/util/util.h |  7 +++++++
 2 files changed, 35 insertions(+)

diff --git a/lib/util/util.c b/lib/util/util.c
index f52f69c6ef0..d2f7160e02e 100644
--- a/lib/util/util.c
+++ b/lib/util/util.c
@@ -47,6 +47,34 @@
  * @brief Misc utility functions
  */
 
+unsigned long int
+strtoul_err(const char *nptr, char **endptr, int base, int *err)
+{
+	unsigned long int val;
+	int saved_errno = errno;
+
+	errno = 0;
+	val = strtoul(nptr, endptr, base);
+	*err = errno;
+
+	errno = saved_errno;
+	return val;
+}
+
+unsigned long long int
+strtoull_err(const char *nptr, char **endptr, int base, int *err)
+{
+	unsigned long long int val;
+	int saved_errno = errno;
+
+	errno = 0;
+	val = strtoull(nptr, endptr, base);
+	*err = errno;
+
+	errno = saved_errno;
+	return val;
+}
+
 /**
  Find a suitable temporary directory. The result should be copied immediately
  as it may be overwritten by a subsequent call.
diff --git a/lib/util/util.h b/lib/util/util.h
index 5a0ce5cdb2a..fcd81759b9c 100644
--- a/lib/util/util.h
+++ b/lib/util/util.h
@@ -21,6 +21,13 @@
 #ifndef __UTIL_SAMBA_UTIL_H__
 #define __UTIL_SAMBA_UTIL_H__
 
+unsigned long int
+strtoul_err(const char *nptr, char **endptr, int base, int *err);
+
+unsigned long long int
+strtoull_err(const char *nptr, char **endptr, int base, int *err);
+
+
 /**
  * Write dump of binary data to a callback
  */
-- 
2.20.1


From f0d311a9f53a8431ab8fe14415aaafec5031e4f4 Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 12:54:07 +0100
Subject: [PATCH 2/8] lib: Use wrapper for string to integer conversion

In order to detect an error during the string to integer
conversion with strtoul/strtoull, the errno variable must
be set to zero before the execution and checked after the
conversion is performed. This is achieved by using the
wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 source3/lib/interface.c     |  6 ++++--
 source3/lib/messages_dgm.c  | 17 +++++++++--------
 source3/lib/namemap_cache.c | 17 +++++++----------
 source3/lib/sysquotas.c     |  7 ++++++-
 source3/lib/tldap_util.c    | 11 ++++++++++-
 source3/wscript_build       |  2 ++
 6 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index a3bc5d24e91..f7c8a875387 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -515,9 +515,11 @@ static void interpret_interface(char *token)
 			return;
 		}
 	} else {
+		int error = 0;
 		char *endp = NULL;
-		unsigned long val = strtoul(p, &endp, 0);
-		if (p == endp || (endp && *endp != '\0')) {
+		unsigned long val = strtoul_err(p, &endp, 0, &error);
+
+		if (p == endp || (endp && *endp != '\0') || error != 0) {
 			DEBUG(2,("interpret_interface: "
 				"can't determine netmask value from %s\n",
 				p));
diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index 37eefeb0a4a..4836697bcf3 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -18,6 +18,7 @@
  */
 
 #include "replace.h"
+#include "util/util.h"
 #include "system/network.h"
 #include "system/filesys.h"
 #include "system/dir.h"
@@ -1442,6 +1443,7 @@ static int messaging_dgm_read_unique(int fd, uint64_t *punique)
 {
 	char buf[25];
 	ssize_t rw_ret;
+	int error = 0;
 	unsigned long long unique;
 	char *endptr;
 
@@ -1451,13 +1453,11 @@ static int messaging_dgm_read_unique(int fd, uint64_t *punique)
 	}
 	buf[rw_ret] = '\0';
 
-	unique = strtoull(buf, &endptr, 10);
-	if ((unique == 0) && (errno == EINVAL)) {
-		return EINVAL;
-	}
-	if ((unique == ULLONG_MAX) && (errno == ERANGE)) {
-		return ERANGE;
+	unique = strtoull_err(buf, &endptr, 10, &error);
+	if (error != 0) {
+		return error;
 	}
+
 	if (endptr[0] != '\n') {
 		return EINVAL;
 	}
@@ -1599,6 +1599,7 @@ int messaging_dgm_forall(int (*fn)(pid_t pid, void *private_data),
 	struct messaging_dgm_context *ctx = global_dgm_context;
 	DIR *msgdir;
 	struct dirent *dp;
+	int error = 0;
 
 	if (ctx == NULL) {
 		return ENOTCONN;
@@ -1621,8 +1622,8 @@ int messaging_dgm_forall(int (*fn)(pid_t pid, void *private_data),
 		unsigned long pid;
 		int ret;
 
-		pid = strtoul(dp->d_name, NULL, 10);
-		if (pid == 0) {
+		pid = strtoul_err(dp->d_name, NULL, 10, &error);
+		if ((pid == 0) || (error != 0)) {
 			/*
 			 * . and .. and other malformed entries
 			 */
diff --git a/source3/lib/namemap_cache.c b/source3/lib/namemap_cache.c
index fa179517f9f..5aa2130c8fd 100644
--- a/source3/lib/namemap_cache.c
+++ b/source3/lib/namemap_cache.c
@@ -22,6 +22,7 @@
 #include "source3/lib/gencache.h"
 #include "lib/util/debug.h"
 #include "lib/util/strv.h"
+#include "lib/util/util.h"
 #include "lib/util/talloc_stack.h"
 #include "lib/util/charset/charset.h"
 #include "libcli/security/dom_sid.h"
@@ -105,6 +106,7 @@ static void namemap_cache_find_sid_parser(
 	const char *domain;
 	const char *name;
 	const char *typebuf;
+	int error = 0;
 	char *endptr;
 	unsigned long type;
 
@@ -123,11 +125,8 @@ static void namemap_cache_find_sid_parser(
 		return;
 	}
 
-	type = strtoul(typebuf, &endptr, 10);
-	if (*endptr != '\0') {
-		return;
-	}
-	if ((type == ULONG_MAX) && (errno == ERANGE)) {
+	type = strtoul_err(typebuf, &endptr, 10, &error);
+	if ((*endptr != '\0') || (errno != 0)) {
 		return;
 	}
 
@@ -253,6 +252,7 @@ static void namemap_cache_find_name_parser(
 	const char *sid_endptr;
 	const char *typebuf;
 	char *endptr;
+	int error = 0;
 	struct dom_sid sid;
 	unsigned long type;
 	bool ok;
@@ -276,11 +276,8 @@ static void namemap_cache_find_name_parser(
 		return;
 	}
 
-	type = strtoul(typebuf, &endptr, 10);
-	if (*endptr != '\0') {
-		return;
-	}
-	if ((type == ULONG_MAX) && (errno == ERANGE)) {
+	type = strtoul_err(typebuf, &endptr, 10, &error);
+	if ((*endptr != '\0') || (errno != 0)) {
 		return;
 	}
 
diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c
index 9b2d37b8375..c89dc96d690 100644
--- a/source3/lib/sysquotas.c
+++ b/source3/lib/sysquotas.c
@@ -250,6 +250,7 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
 		char *p2;
 		char *syscmd = NULL;
 		int _id = -1;
+		int error = 0;
 
 		switch(qtype) {
 			case SMB_USER_QUOTA_TYPE:
@@ -282,7 +283,11 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
 
 			/* we need to deal with long long unsigned here, if supported */
 
-			dp->qflags = strtoul(line, &p2, 10);
+			dp->qflags = strtoul_err(line, &p2, 10, &error);
+			if (error != 0) {
+				goto invalid_param;
+			}
+
 			p = p2;
 			while (p && *p && isspace(*p)) {
 				p++;
diff --git a/source3/lib/tldap_util.c b/source3/lib/tldap_util.c
index 508c6c02f80..3135a8c4396 100644
--- a/source3/lib/tldap_util.c
+++ b/source3/lib/tldap_util.c
@@ -389,13 +389,22 @@ bool tldap_pull_uint64(struct tldap_message *msg, const char *attr,
 {
 	char *str;
 	uint64_t result;
+	int error = 0;
 
 	str = tldap_talloc_single_attribute(msg, attr, talloc_tos());
 	if (str == NULL) {
 		DEBUG(10, ("Could not find attribute %s\n", attr));
 		return false;
 	}
-	result = strtoull(str, NULL, 10);
+
+	result = strtoull_err(str, NULL, 10, &error);
+	if (error != 0) {
+		DBG_DEBUG("Attribute conversion failed (%s)\n",
+			  strerror(error));
+		TALLOC_FREE(str);
+		return false;
+	}
+
 	TALLOC_FREE(str);
 	*presult = result;
 	return true;
diff --git a/source3/wscript_build b/source3/wscript_build
index f25a27ba3a8..2b5b3ca2c4f 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -367,6 +367,7 @@ bld.SAMBA3_LIBRARY('messages_dgm',
                         PTHREADPOOL
                         msghdr
                         genrand
+			samba-util
                         ''',
                    private_library=True)
 
@@ -1362,6 +1363,7 @@ bld.RECURSE('smbd/notifyd')
 bld.RECURSE('rpcclient')
 bld.RECURSE('utils')
 bld.RECURSE('nmbd')
+bld.RECURSE('lib/util')
 
 bld.ENFORCE_GROUP_ORDERING()
 bld.CHECK_PROJECT_RULES()
-- 
2.20.1


From 2f5dec8f2cd0aba3a1a56a1c7298b1e680f355c4 Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 13:12:09 +0100
Subject: [PATCH 3/8] groupdb: Use wrapper for string to integer conversion

In order to detect an error during the string to integer
conversion with strtoul/strtoull, the errno variable must
be set to zero before the execution and checked after the
conversion is performed. This is achieved by using the
wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 source3/groupdb/mapping.c     | 11 ++++++++++-
 source3/groupdb/mapping_tdb.c | 12 ++++++++----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c
index 43722e777d4..77eb0d6e5cd 100644
--- a/source3/groupdb/mapping.c
+++ b/source3/groupdb/mapping.c
@@ -208,6 +208,7 @@ int smb_create_group(const char *unix_group, gid_t *new_gid)
 	char *add_script = NULL;
 	int 	ret = -1;
 	int 	fd = 0;
+	int error = 0;
 
 	*new_gid = 0;
 
@@ -244,7 +245,15 @@ int smb_create_group(const char *unix_group, gid_t *new_gid)
 			nread = read(fd, output, sizeof(output)-1);
 			if (nread > 0) {
 				output[nread] = '\0';
-				*new_gid = (gid_t)strtoul(output, NULL, 10);
+				*new_gid = (gid_t)strtoul_err(output,
+							      NULL,
+							      10,
+							      &error);
+				if (error != 0) {
+					*new_gid = 0;
+					close(fd);
+					return -1;
+				}
 			}
 
 			close(fd);
diff --git a/source3/groupdb/mapping_tdb.c b/source3/groupdb/mapping_tdb.c
index d6a06ef199b..c80ff1f859a 100644
--- a/source3/groupdb/mapping_tdb.c
+++ b/source3/groupdb/mapping_tdb.c
@@ -860,6 +860,7 @@ static int convert_ldb_record(TDB_CONTEXT *ltdb, TDB_DATA key,
 	char *q;
 	uint32_t num_mem = 0;
 	struct dom_sid *members = NULL;
+	int error = 0;
 
 	p = (uint8_t *)data.dptr;
 	if (data.dsize < 8) {
@@ -974,8 +975,8 @@ static int convert_ldb_record(TDB_CONTEXT *ltdb, TDB_DATA key,
 			/* we ignore unknown or uninteresting attributes
 			 * (objectclass, etc.) */
 			if (strcasecmp_m(name, "gidNumber") == 0) {
-				map->gid = strtoul(val, &q, 10);
-				if (*q) {
+				map->gid = strtoul_err(val, &q, 10, &error);
+				if (*q || (error != 0)) {
 					errno = EIO;
 					goto failed;
 				}
@@ -985,8 +986,11 @@ static int convert_ldb_record(TDB_CONTEXT *ltdb, TDB_DATA key,
 					goto failed;
 				}
 			} else if (strcasecmp_m(name, "sidNameUse") == 0) {
-				map->sid_name_use = strtoul(val, &q, 10);
-				if (*q) {
+				map->sid_name_use = strtoul_err(val,
+								&q,
+								10,
+								&error);
+				if (*q || (error != 0)) {
 					errno = EIO;
 					goto failed;
 				}
-- 
2.20.1


From 60fb2bce92ad91867c28468381b553f8951ad645 Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 13:36:45 +0100
Subject: [PATCH 4/8] utils: Use wrapper for string to integer conversion

In order to detect an error during the string to integer
conversion with strtoul/strtoull, the errno variable must
be set to zero before the execution and checked after the
conversion is performed. This is achieved by using the
wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 source3/utils/net_idmap.c        |  9 +++------
 source3/utils/net_registry.c     | 14 ++++++++++++--
 source3/utils/net_rpc_registry.c |  8 +++++++-
 source3/utils/net_sam.c          |  5 +++--
 source3/utils/pdbedit.c          | 12 +++++++++---
 source3/utils/regedit_dialog.c   |  5 +++--
 6 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/source3/utils/net_idmap.c b/source3/utils/net_idmap.c
index b49d5f43381..f6c9f3a1a3d 100644
--- a/source3/utils/net_idmap.c
+++ b/source3/utils/net_idmap.c
@@ -628,8 +628,9 @@ static bool parse_uint32(const char *str, uint32_t *result)
 {
 	unsigned long val;
 	char *endptr;
+	int error = 0;
 
-	val = strtoul(str, &endptr, 10);
+	val = strtoul_err(str, &endptr, 10, &error);
 
 	if (str == endptr) {
 		return false;
@@ -637,11 +638,7 @@ static bool parse_uint32(const char *str, uint32_t *result)
 	if (*endptr != '\0') {
 		return false;
 	}
-	if ((val == ULONG_MAX) && (errno == ERANGE)) {
-		return false;
-	}
-	if ((val & UINT32_MAX) != val) {
-		/* overflow */
+	if (error != 0) {
 		return false;
 	}
 	*result = val;		/* Potential crop */
diff --git a/source3/utils/net_registry.c b/source3/utils/net_registry.c
index 01a36b20e7c..b7711873561 100644
--- a/source3/utils/net_registry.c
+++ b/source3/utils/net_registry.c
@@ -509,7 +509,13 @@ static int net_registry_setvalue(struct net_context *c, int argc,
 	}
 
 	if (strequal(argv[2], "dword")) {
-		uint32_t v = strtoul(argv[3], NULL, 10);
+		int error = 0;
+		uint32_t v = strtoul_err(argv[3], NULL, 10, &error);
+
+		if (error != 0) {
+			goto done;
+		}
+
 		value.type = REG_DWORD;
 		value.data = data_blob_talloc(ctx, NULL, 4);
 		SIVAL(value.data.data, 0, v);
@@ -641,7 +647,11 @@ static int net_registry_increment(struct net_context *c, int argc,
 
 	state.increment = 1;
 	if (argc == 3) {
-		state.increment = strtoul(argv[2], NULL, 10);
+		int error = 0;
+		state.increment = strtoul_err(argv[2], NULL, 10, &error);
+		if (error != 0) {
+			goto done;
+		}
 	}
 
 	status = g_lock_do(string_term_tdb_data("registry_increment_lock"),
diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c
index 19b73fd7042..dc51137e15b 100644
--- a/source3/utils/net_rpc_registry.c
+++ b/source3/utils/net_rpc_registry.c
@@ -603,7 +603,13 @@ static NTSTATUS rpc_registry_setvalue_internal(struct net_context *c,
 	}
 
 	if (strequal(argv[2], "dword")) {
-		uint32_t v = strtoul(argv[3], NULL, 10);
+		int error = 0;
+		uint32_t v = strtoul_err(argv[3], NULL, 10, &error);
+
+		if (error != 0) {
+			goto error;
+		}
+
 		value.type = REG_DWORD;
 		value.data = data_blob_talloc(mem_ctx, NULL, 4);
 		SIVAL(value.data.data, 0, v);
diff --git a/source3/utils/net_sam.c b/source3/utils/net_sam.c
index 5a9d1792d51..fc2a7baacef 100644
--- a/source3/utils/net_sam.c
+++ b/source3/utils/net_sam.c
@@ -484,6 +484,7 @@ static int net_sam_policy_set(struct net_context *c, int argc, const char **argv
 	uint32_t old_value = 0;
 	enum pdb_policy_type field;
 	char *endptr;
+	int err = 0;
 
         if (argc != 2 || c->display_usage) {
                 d_fprintf(stderr, "%s\n%s",
@@ -500,9 +501,9 @@ static int net_sam_policy_set(struct net_context *c, int argc, const char **argv
 		value = -1;
 	}
 	else {
-		value = strtoul(argv[1], &endptr, 10);
+		value = strtoul_err(argv[1], &endptr, 10, &err);
 
-		if ((endptr == argv[1]) || (endptr[0] != '\0')) {
+		if ((endptr == argv[1]) || (endptr[0] != '\0') || (err != 0)) {
 			d_printf(_("Unable to set policy \"%s\"! Invalid value "
 				 "\"%s\".\n"),
 				 account_policy, argv[1]);
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index 585f1bfada3..51db6710ff3 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -598,9 +598,15 @@ static int set_user_info(const char *username, const char *fullname,
 		time_t value = get_time_t_max();
 
 		if (strcmp(kickoff_time, "never") != 0) {
-			uint32_t num = strtoul(kickoff_time, &endptr, 10);
-
-			if ((endptr == kickoff_time) || (endptr[0] != '\0')) {
+			int error = 0;
+			uint32_t num = strtoul_err(kickoff_time,
+						   &endptr,
+						   10,
+						   &error);
+
+			if ((endptr == kickoff_time) ||
+			    (endptr[0] != '\0') ||
+			    (error != 0)) {
 				fprintf(stderr, "Failed to parse kickoff time\n");
 				return -1;
 			}
diff --git a/source3/utils/regedit_dialog.c b/source3/utils/regedit_dialog.c
index dcce66bf208..aeea70ac22e 100644
--- a/source3/utils/regedit_dialog.c
+++ b/source3/utils/regedit_dialog.c
@@ -1032,6 +1032,7 @@ bool dialog_section_text_field_get_uint(struct dialog_section *section,
 	bool rv;
 	const char *buf;
 	char *endp;
+	int error = 0;
 	struct dialog_section_text_field *text_field =
 		talloc_get_type_abort(section, struct dialog_section_text_field);
 
@@ -1041,9 +1042,9 @@ bool dialog_section_text_field_get_uint(struct dialog_section *section,
 	if (buf == NULL) {
 		return false;
 	}
-	*out = strtoull(buf, &endp, 0);
+	*out = strtoull_err(buf, &endp, 0, &error);
 	rv = true;
-	if (endp == buf || endp == NULL || endp[0] != '\0') {
+	if (endp == buf || endp == NULL || endp[0] != '\0' || error != 0) {
 		rv = false;
 	}
 
-- 
2.20.1


From 470ec280c46e438f9b033ef68210d57062fa0ef9 Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 13:57:15 +0100
Subject: [PATCH 5/8] passdb: Use wrapper for string to integer conversion

In order to detect an error during the string to integer
conversion with strtoul/strtoull, the errno variable must
be set to zero before the execution and checked after the
conversion is performed. This is achieved by using the
wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 source3/passdb/account_pol.c |  7 +++-
 source3/passdb/pdb_ldap.c    | 72 +++++++++++++++++++++++++++++-------
 source3/passdb/pdb_tdb.c     |  6 ++-
 3 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/source3/passdb/account_pol.c b/source3/passdb/account_pol.c
index e566eca78eb..b1463c647b7 100644
--- a/source3/passdb/account_pol.c
+++ b/source3/passdb/account_pol.c
@@ -456,7 +456,12 @@ bool cache_account_policy_get(enum pdb_policy_type type, uint32_t *value)
 	}
 
 	if (gencache_get(cache_key, talloc_tos(), &cache_value, NULL)) {
-		uint32_t tmp = strtoul(cache_value, NULL, 10);
+		int error = 0;
+		uint32_t tmp = strtoul_err(cache_value, NULL, 10, &error);
+
+		if (error != 0) {
+			goto done;
+		}
 		*value = tmp;
 		ret = True;
 	}
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 7f8903ba96d..273baac8c7f 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -982,6 +982,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 		struct dom_sid mapped_gsid;
 		const struct dom_sid *primary_gsid;
 		struct unixid id;
+		int error = 0;
 
 		ZERO_STRUCT(unix_pw);
 
@@ -995,7 +996,11 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 				ctx);
 		if (temp) {
 			/* We've got a uid, feed the cache */
-			unix_pw.pw_uid = strtoul(temp, NULL, 10);
+			unix_pw.pw_uid = strtoul_err(temp, NULL, 10, &error);
+			if (error != 0) {
+				DBG_ERR("Failed to convert UID\n");
+				goto fn_exit;
+			}
 			have_uid = true;
 		}
 		temp = smbldap_talloc_single_attribute(
@@ -1005,7 +1010,11 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 				ctx);
 		if (temp) {
 			/* We've got a uid, feed the cache */
-			unix_pw.pw_gid = strtoul(temp, NULL, 10);
+			unix_pw.pw_gid = strtoul_err(temp, NULL, 10, &error);
+			if (error != 0) {
+				DBG_ERR("Failed to convert GID\n");
+				goto fn_exit;
+			}
 			have_gid = true;
 		}
 		unix_pw.pw_gecos = smbldap_talloc_single_attribute(
@@ -2879,6 +2888,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 	uint32_t num_gids;
 	char *gidstr;
 	gid_t primary_gid = -1;
+	int error = 0;
 
 	*pp_sids = NULL;
 	num_sids = 0;
@@ -2928,7 +2938,11 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 				ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
 				goto done;
 			}
-			primary_gid = strtoul(gidstr, NULL, 10);
+			primary_gid = strtoul_err(gidstr, NULL, 10, &error);
+			if (error != 0) {
+				DBG_ERR("Failed to convert GID\n");
+				goto done;
+			}
 			break;
 		default:
 			DEBUG(1, ("found more than one account with the same user name ?!\n"));
@@ -2996,10 +3010,11 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 						  str, sizeof(str)-1))
 			continue;
 
-		gid = strtoul(str, &end, 10);
+		gid = strtoul_err(str, &end, 10, &error);
 
-		if (PTR_DIFF(end, str) != strlen(str))
+		if ((PTR_DIFF(end, str) != strlen(str)) || (error != 0)) {
 			goto done;
+		}
 
 		if (gid == primary_gid) {
 			sid_copy(&(*pp_sids)[0], &sid);
@@ -4924,6 +4939,7 @@ static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
 	int rc;
 	uint32_t nextRid = 0;
 	const char *dn;
+	int error = 0;
 
 	TALLOC_CTX *mem_ctx;
 
@@ -4959,21 +4975,33 @@ static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
 	value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
 						"sambaNextRid",	mem_ctx);
 	if (value != NULL) {
-		uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
+		uint32_t tmp = (uint32_t)strtoul_err(value, NULL, 10, &error);
+		if (error != 0) {
+			goto done;
+		}
+
 		nextRid = MAX(nextRid, tmp);
 	}
 
 	value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
 						"sambaNextUserRid", mem_ctx);
 	if (value != NULL) {
-		uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
+		uint32_t tmp = (uint32_t)strtoul_err(value, NULL, 10, &error);
+		if (error != 0) {
+			goto done;
+		}
+
 		nextRid = MAX(nextRid, tmp);
 	}
 
 	value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
 						"sambaNextGroupRid", mem_ctx);
 	if (value != NULL) {
-		uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
+		uint32_t tmp = (uint32_t)strtoul_err(value, NULL, 10, &error);
+		if (error != 0) {
+			goto done;
+		}
+
 		nextRid = MAX(nextRid, tmp);
 	}
 
@@ -5043,6 +5071,7 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
 	struct ldapsam_privates *priv =
 		(struct ldapsam_privates *)methods->private_data;
 	char *filter;
+	int error = 0;
 	struct dom_sid_buf buf;
 	const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
 				NULL };
@@ -5106,7 +5135,11 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
 			goto done;
 		}
 
-		id->id = strtoul(gid_str, NULL, 10);
+		id->id = strtoul_err(gid_str, NULL, 10, &error);
+		if (error != 0) {
+			goto done;
+		}
+
 		id->type = ID_TYPE_GID;
 		ret = True;
 		goto done;
@@ -5122,9 +5155,12 @@ static bool ldapsam_sid_to_id(struct pdb_methods *methods,
 		goto done;
 	}
 
-	id->id = strtoul(value, NULL, 10);
-	id->type = ID_TYPE_UID;
+	id->id = strtoul_err(value, NULL, 10, &error);
+	if (error != 0) {
+		goto done;
+	}
 
+	id->type = ID_TYPE_UID;
 	ret = True;
  done:
 	TALLOC_FREE(mem_ctx);
@@ -5665,6 +5701,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
 	struct dom_sid_buf buf;
 	gid_t gid = -1;
 	int rc;
+	int error = 0;
 
 	groupname = escape_ldap_string(talloc_tos(), name);
 	filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))",
@@ -5709,7 +5746,11 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
 		}
 
-		gid = strtoul(tmp, NULL, 10);
+		gid = strtoul_err(tmp, NULL, 10, &error);
+		if (error != 0) {
+			DBG_ERR("Failed to convert gidNumber\n");
+			return NT_STATUS_UNSUCCESSFUL;
+		}
 
 		dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
 		if (!dn) {
@@ -5916,6 +5957,7 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
 	struct dom_sid member_sid;
 	struct dom_sid_buf buf;
 	int rc;
+	int error = 0;
 
 	switch (modop) {
 	case LDAP_MOD_ADD:
@@ -5981,7 +6023,11 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
 		}
 
-		user_gid = strtoul(gidstr, NULL, 10);
+		user_gid = strtoul_err(gidstr, NULL, 10, &error);
+		if (error != 0) {
+			DBG_ERR("Failed to convert user gid\n");
+			return NT_STATUS_UNSUCCESSFUL;
+		}
 
 		if (!sid_to_gid(&group_sid, &group_gid)) {
 			DEBUG (0, ("ldapsam_change_groupmem: Unable to get group gid from SID!\n"));
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index 91735ff7084..067150334a3 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -1173,6 +1173,7 @@ static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
 		private_data, struct tdbsam_search_state);
 	size_t prefixlen = strlen(RIDPREFIX);
 	uint32_t rid;
+	int error = 0;
 	TDB_DATA key;
 
 	key = dbwrap_record_get_key(rec);
@@ -1182,7 +1183,10 @@ static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
 		return 0;
 	}
 
-	rid = strtoul((char *)key.dptr+prefixlen, NULL, 16);
+	rid = strtoul_err((char *)key.dptr+prefixlen, NULL, 16, &error);
+	if (error != 0) {
+		return 0;
+	}
 
 	ADD_TO_LARGE_ARRAY(state, uint32_t, rid, &state->rids, &state->num_rids,
 			   &state->array_size);
-- 
2.20.1


From a3fad7a6557c4ceb71e44a7bd04c989c8c2b258c Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 14:07:39 +0100
Subject: [PATCH 6/8] winbindd: Use wrapper for string to integer conversion

In order to detect an error during the string to integer
conversion with strtoul/strtoull, the errno variable must
be set to zero before the execution and checked after the
conversion is performed. This is achieved by using the
wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 source3/winbindd/idmap_ldap.c          | 17 ++++++++++++-----
 source3/winbindd/winbindd_lookuprids.c |  6 ++++--
 source3/winbindd/winbindd_util.c       | 24 +++++++++++++++++++-----
 3 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c
index 17cc7404f12..9a4815be726 100644
--- a/source3/winbindd/idmap_ldap.c
+++ b/source3/winbindd/idmap_ldap.c
@@ -222,6 +222,7 @@ static NTSTATUS idmap_ldap_allocate_id_internal(struct idmap_domain *dom,
 	const char **attr_list;
 	const char *type;
 	struct idmap_ldap_context *ctx;
+	int error = 0;
 
 	/* Only do query if we are online */
 	if (idmap_is_offline())	{
@@ -299,7 +300,11 @@ static NTSTATUS idmap_ldap_allocate_id_internal(struct idmap_domain *dom,
 		goto done;
 	}
 
-	xid->id = strtoul(id_str, NULL, 10);
+	xid->id = strtoul_err(id_str, NULL, 10, &error);
+	if (errno != 0) {
+		ret = NT_STATUS_UNSUCCESSFUL;
+		goto done;
+	}
 
 	/* make sure we still have room to grow */
 
@@ -641,6 +646,7 @@ static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
 	int count;
 	int rc;
 	int i;
+	int error = 0;
 
 	/* Only do query if we are online */
 	if (idmap_is_offline())	{
@@ -769,8 +775,8 @@ again:
 			continue;
 		}
 
-		id = strtoul(tmp, NULL, 10);
-		if (!idmap_unix_id_is_in_range(id, dom)) {
+		id = strtoul_err(tmp, NULL, 10, &error);
+		if (error != 0 || !idmap_unix_id_is_in_range(id, dom)) {
 			DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
 				  "Filtered!\n", id,
 				  dom->low_id, dom->high_id));
@@ -947,6 +953,7 @@ again:
 		struct dom_sid sid;
 		struct dom_sid_buf buf;
 		uint32_t id;
+		int error = 0;
 
 		if (i == 0) { /* first entry */
 			entry = ldap_first_entry(
@@ -1005,8 +1012,8 @@ again:
 			continue;
 		}
 
-		id = strtoul(tmp, NULL, 10);
-		if (!idmap_unix_id_is_in_range(id, dom)) {
+		id = strtoul_err(tmp, NULL, 10, &error);
+		if (error != 0 || !idmap_unix_id_is_in_range(id, dom)) {
 			DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
 				  "Filtered!\n", id,
 				  dom->low_id, dom->high_id));
diff --git a/source3/winbindd/winbindd_lookuprids.c b/source3/winbindd/winbindd_lookuprids.c
index 1e80b78a92e..959a4a7db38 100644
--- a/source3/winbindd/winbindd_lookuprids.c
+++ b/source3/winbindd/winbindd_lookuprids.c
@@ -182,8 +182,10 @@ static bool parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
 
 	for (i=0; i<num_rids; i++) {
 		char *q;
-		rids[i] = strtoul(p, &q, 10);
-		if (*q != '\n') {
+		int error = 0;
+
+		rids[i] = strtoul_err(p, &q, 10, &error);
+		if (error != 0 || *q != '\n') {
 			DEBUG(0, ("Got invalid ridstr: %s\n", p));
 			return false;
 		}
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index d266eb3048e..91a2f6ef197 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -461,6 +461,7 @@ static void trustdom_list_done(struct tevent_req *req)
 		uint32_t trust_type;
 		uint32_t trust_attribs;
 		uint32_t trust_flags;
+		int error = 0;
 
 		DBG_DEBUG("parsing response line '%s'\n", p);
 
@@ -506,7 +507,11 @@ static void trustdom_list_done(struct tevent_req *req)
 			break;
 		}
 
-		trust_flags = (uint32_t)strtoul(q, NULL, 10);
+		trust_flags = (uint32_t)strtoul_err(q, NULL, 10, &error);
+		if (error != 0) {
+			DBG_ERR("Failed to convert trust_flags\n");
+			break;
+		}
 
 		q = strtok(NULL, "\\");
 		if (q == NULL) {
@@ -514,7 +519,11 @@ static void trustdom_list_done(struct tevent_req *req)
 			break;
 		}
 
-		trust_type = (uint32_t)strtoul(q, NULL, 10);
+		trust_type = (uint32_t)strtoul_err(q, NULL, 10, &error);
+		if (error != 0) {
+			DBG_ERR("Failed to convert trust_type\n");
+			break;
+		}
 
 		q = strtok(NULL, "\n");
 		if (q == NULL) {
@@ -522,7 +531,11 @@ static void trustdom_list_done(struct tevent_req *req)
 			break;
 		}
 
-		trust_attribs = (uint32_t)strtoul(q, NULL, 10);
+		trust_attribs = (uint32_t)strtoul_err(q, NULL, 10, &error);
+		if (error != 0) {
+			DBG_ERR("Failed to convert trust_attribs\n");
+			break;
+		}
 
 		if (!within_forest) {
 			trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
@@ -2142,6 +2155,7 @@ bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
 		struct unixid xid;
 		unsigned long long id;
 		char *endp;
+		int error = 0;
 
 		switch (p[0]) {
 		case 'U':
@@ -2156,8 +2170,8 @@ bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
 
 		p += 1;
 
-		id = strtoull(p, &endp, 10);
-		if ((id == ULLONG_MAX) && (errno == ERANGE)) {
+		id = strtoull_err(p, &endp, 10, &error);
+		if (error != 0) {
 			goto fail;
 		}
 		if (*endp != '\n') {
-- 
2.20.1


From 01c75f7f55e59f0931ae071008a81859cbfb57e9 Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 14:30:15 +0100
Subject: [PATCH 7/8] modules: Use wrapper for string to integer conversion

In order to detect an error during the string to integer
conversion with strtoul/strtoull, the errno variable must
be set to zero before the execution and checked after the
conversion is performed. This is achieved by using the
wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 source3/modules/vfs_preopen.c | 6 +++++-
 source3/modules/vfs_snapper.c | 5 +++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/source3/modules/vfs_preopen.c b/source3/modules/vfs_preopen.c
index 84b13556195..24d33fafacd 100644
--- a/source3/modules/vfs_preopen.c
+++ b/source3/modules/vfs_preopen.c
@@ -345,6 +345,7 @@ static bool preopen_parse_fname(const char *fname, unsigned long *pnum,
 	const char *p;
 	char *q = NULL;
 	unsigned long num;
+	int error = 0;
 
 	p = strrchr_m(fname, '/');
 	if (p == NULL) {
@@ -363,7 +364,10 @@ static bool preopen_parse_fname(const char *fname, unsigned long *pnum,
 		return false;
 	}
 
-	num = strtoul(p, (char **)&q, 10);
+	num = strtoul_err(p, (char **)&q, 10, &error);
+	if (error != 0) {
+		return false;
+	}
 
 	if (num+1 < num) {
 		/* overflow */
diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c
index 443a940b17a..0f52f9e71c5 100644
--- a/source3/modules/vfs_snapper.c
+++ b/source3/modules/vfs_snapper.c
@@ -1218,6 +1218,7 @@ static NTSTATUS snapper_snap_path_to_id(TALLOC_CTX *mem_ctx,
 	char *str_idx;
 	char *str_end;
 	uint32_t snap_id;
+	int error = 0;
 
 	path_dup = talloc_strdup(mem_ctx, snap_path);
 	if (path_dup == NULL) {
@@ -1250,8 +1251,8 @@ static NTSTATUS snapper_snap_path_to_id(TALLOC_CTX *mem_ctx,
 	}
 
 	str_idx++;
-	snap_id = strtoul(str_idx, &str_end, 10);
-	if (str_idx == str_end) {
+	snap_id = strtoul_err(str_idx, &str_end, 10, &error);
+	if (error != 0 || str_idx == str_end) {
 		talloc_free(path_dup);
 		return NT_STATUS_INVALID_PARAMETER;
 	}
-- 
2.20.1


From 86c1636ed3af702b841a3bf2553bfa2f849e156d Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Mon, 28 Jan 2019 14:35:30 +0100
Subject: [PATCH 8/8] rpcclient: Use wrapper for string to integer conversion

In order to detect an error during the string to integer
conversion with strtoul/strtoull, the errno variable must
be set to zero before the execution and checked after the
conversion is performed. This is achieved by using the
wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 source3/rpcclient/cmd_samr.c    | 7 ++++++-
 source3/rpcclient/cmd_spoolss.c | 8 +++++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c
index d55d1648c91..32a27ff3669 100644
--- a/source3/rpcclient/cmd_samr.c
+++ b/source3/rpcclient/cmd_samr.c
@@ -1406,13 +1406,18 @@ static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli,
 	uint32_t alias_rid;
 	uint32_t access_mask = MAXIMUM_ALLOWED_ACCESS;
 	struct dcerpc_binding_handle *b = cli->binding_handle;
+	int error = 0;
 
 	if (argc != 3) {
 		printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
 		return NT_STATUS_OK;
 	}
 
-	alias_rid = strtoul(argv[2], NULL, 10);
+	alias_rid = strtoul_err(argv[2], NULL, 10, &error);
+	if (error != 0) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
 
 	/* Open SAMR handle */
 
diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c
index 8d330afdeb0..83839b24dd3 100644
--- a/source3/rpcclient/cmd_spoolss.c
+++ b/source3/rpcclient/cmd_spoolss.c
@@ -2642,6 +2642,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
 	union spoolss_PrinterData data;
 	DATA_BLOB blob;
 	struct dcerpc_binding_handle *b = cli->binding_handle;
+	int error = 0;
 
 	/* parse the command arguments */
 	if (argc < 5) {
@@ -2707,7 +2708,12 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
 		W_ERROR_HAVE_NO_MEMORY(data.string);
 		break;
 	case REG_DWORD:
-		data.value = strtoul(argv[4], NULL, 10);
+		data.value = strtoul_err(argv[4], NULL, 10, &error);
+		if (error != 0) {
+			result = WERR_INVALID_PARAMETER;
+			goto done;
+		}
+
 		break;
 	case REG_BINARY:
 		data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
-- 
2.20.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190128/9e6c35e8/signature.sig>


More information about the samba-technical mailing list