[Asterisk-code-review] conversions.c: Add conversions for largest max sized integer (...asterisk[16])

Friendly Automation asteriskteam at digium.com
Wed May 15 07:01:44 CDT 2019


Friendly Automation has submitted this change and it was merged. ( https://gerrit.asterisk.org/c/asterisk/+/11357 )

Change subject: conversions.c: Add conversions for largest max sized integer
......................................................................

conversions.c: Add conversions for largest max sized integer

Added a conversion for umax (largest maximum sized integer allowed). Adjusted
the other current conversion functions (uint and ulong) to be derivatives of
the umax conversion since they are simply subsets of umax.

Also made the negative check move the pointer on spaces since strtoumax does it
anyways.

Change-Id: I56c2ef2629d49b524c8df58af12951c181f81f08
---
M include/asterisk/conversions.h
M main/conversions.c
M tests/test_conversions.c
3 files changed, 95 insertions(+), 14 deletions(-)

Approvals:
  Benjamin Keith Ford: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, approved
  Friendly Automation: Approved for Submit



diff --git a/include/asterisk/conversions.h b/include/asterisk/conversions.h
index 2997760..55906e6 100644
--- a/include/asterisk/conversions.h
+++ b/include/asterisk/conversions.h
@@ -23,6 +23,8 @@
 #ifndef _ASTERISK_CONVERSIONS_H
 #define _ASTERISK_CONVERSIONS_H
 
+#include <stdint.h>
+
 /*!
  * \brief Convert the given string to an unsigned integer
  *
@@ -59,4 +61,22 @@
  */
 int ast_str_to_ulong(const char *str, unsigned long *res);
 
+/*!
+ * \brief Convert the given string to an unsigned max size integer
+ *
+ * This function will return failure for the following reasons:
+ *
+ *   The given string to convert is NULL
+ *   The given string to convert is empty.
+ *   The given string to convert is negative (starts with a '-')
+ *   The given string to convert contains non numeric values
+ *   Once converted the number is out of range (greater than UINTMAX_MAX)
+ *
+ * \param str The string to convert
+ * \param res [out] The converted value
+ *
+ * \returns -1 if it fails to convert, 0 on success
+ */
+int ast_str_to_umax(const char *str, uintmax_t *res);
+
 #endif /* _ASTERISK_CONVERSIONS_H */
diff --git a/main/conversions.c b/main/conversions.c
index e73e1a2..2fd3146 100644
--- a/main/conversions.c
+++ b/main/conversions.c
@@ -26,22 +26,26 @@
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
-#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
 
 #include "asterisk/conversions.h"
 
-static int str_is_negative(const char *str)
+static int str_is_negative(const char **str)
 {
-	/* Ignore any preceding white space */
-	while (isspace(*str) && *++str);
-	return *str == '-';
+	/*
+	 * Ignore any preceding white space. It's okay to move the pointer here
+	 * since the converting function would do the same, i.e. skip white space.
+	 */
+	while (isspace(**str)) ++*str;
+	return **str == '-';
 }
 
 int ast_str_to_uint(const char *str, unsigned int *res)
 {
-	unsigned long val;
+	uintmax_t val;
 
-	if (ast_str_to_ulong(str, &val) || val > UINT_MAX) {
+	if (ast_str_to_umax(str, &val) || val > UINT_MAX) {
 		return -1;
 	}
 
@@ -51,15 +55,27 @@
 
 int ast_str_to_ulong(const char *str, unsigned long *res)
 {
-	char *end;
-	unsigned long val;
+	uintmax_t val;
 
-	if (!str || str_is_negative(str)) {
+	if (ast_str_to_umax(str, &val) || val > ULONG_MAX) {
+		return -1;
+	}
+
+	*res = val;
+	return 0;
+}
+
+int ast_str_to_umax(const char *str, uintmax_t *res)
+{
+	char *end;
+	uintmax_t val;
+
+	if (!str || str_is_negative(&str)) {
 		return -1;
 	}
 
 	errno = 0;
-	val = strtoul(str, &end, 0);
+	val = strtoumax(str, &end, 0);
 
 	/*
 	 * If str equals end then no digits were found. If end is not pointing to
@@ -67,11 +83,10 @@
 	 * converted, but some characters that could not, which we'll consider
 	 * invalid.
 	 */
-	if ((str == end || *end != '\0' || (errno == ERANGE && val == ULONG_MAX))) {
+	if ((str == end || *end != '\0' || (errno == ERANGE && val == UINTMAX_MAX))) {
 		return -1;
 	}
 
 	*res = val;
 	return 0;
-
 }
diff --git a/tests/test_conversions.c b/tests/test_conversions.c
index 689aba9..1a765b4 100644
--- a/tests/test_conversions.c
+++ b/tests/test_conversions.c
@@ -62,6 +62,7 @@
 	}
 
 	ast_test_validate(test, ast_str_to_uint(NULL, &val));
+	ast_test_validate(test, ast_str_to_uint("\0", &val));
 	ast_test_validate(test, ast_str_to_uint(invalid, &val));
 	ast_test_validate(test, ast_str_to_uint(invalid_partial, &val));
 	ast_test_validate(test, ast_str_to_uint(negative, &val));
@@ -103,6 +104,7 @@
 	}
 
 	ast_test_validate(test, ast_str_to_ulong(NULL, &val));
+	ast_test_validate(test, ast_str_to_ulong("\0", &val));
 	ast_test_validate(test, ast_str_to_ulong(invalid, &val));
 	ast_test_validate(test, ast_str_to_ulong(invalid_partial, &val));
 	ast_test_validate(test, ast_str_to_ulong(negative, &val));
@@ -119,10 +121,53 @@
 	return AST_TEST_PASS;
 }
 
+AST_TEST_DEFINE(str_to_umax)
+{
+	const char *invalid = "abc";
+	const char *invalid_partial = "7abc";
+	const char *negative = "-7";
+	const char *negative_spaces = "  -7";
+	const char *out_of_range = "99999999999999999999999999999999999999999999999999";
+	const char *spaces = "  ";
+	const char *valid = "7";
+	const char *valid_spaces = "  7";
+	uintmax_t val;
+	char str[64];
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = __func__;
+		info->category = CATEGORY;
+		info->summary = "convert a string to an unsigned max size integer";
+		info->description = info->summary;
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	ast_test_validate(test, ast_str_to_umax(NULL, &val));
+	ast_test_validate(test, ast_str_to_umax("\0", &val));
+	ast_test_validate(test, ast_str_to_umax(invalid, &val));
+	ast_test_validate(test, ast_str_to_umax(invalid_partial, &val));
+	ast_test_validate(test, ast_str_to_umax(negative, &val));
+	ast_test_validate(test, ast_str_to_umax(negative_spaces, &val));
+	ast_test_validate(test, ast_str_to_umax(out_of_range, &val));
+	ast_test_validate(test, ast_str_to_umax(spaces, &val));
+	ast_test_validate(test, !ast_str_to_umax(valid, &val));
+	ast_test_validate(test, !ast_str_to_umax(valid_spaces, &val));
+
+	ast_test_validate(test, snprintf(str, sizeof(str), "%lu", UINTMAX_MAX) > 0);
+	ast_test_validate(test, !ast_str_to_umax(str, &val));
+	ast_test_validate(test, val == UINTMAX_MAX);
+
+	return AST_TEST_PASS;
+}
+
 static int load_module(void)
 {
 	AST_TEST_REGISTER(str_to_uint);
 	AST_TEST_REGISTER(str_to_ulong);
+	AST_TEST_REGISTER(str_to_umax);
 	return AST_MODULE_LOAD_SUCCESS;
 }
 
@@ -130,7 +175,8 @@
 {
 	AST_TEST_UNREGISTER(str_to_uint);
 	AST_TEST_UNREGISTER(str_to_ulong);
+	AST_TEST_UNREGISTER(str_to_umax);
 	return 0;
 }
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "URI test module");
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Conversions test module");

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/11357
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-Change-Id: I56c2ef2629d49b524c8df58af12951c181f81f08
Gerrit-Change-Number: 11357
Gerrit-PatchSet: 1
Gerrit-Owner: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Benjamin Keith Ford <bford at digium.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20190515/c26598c7/attachment-0001.html>


More information about the asterisk-code-review mailing list