summaryrefslogtreecommitdiffstats
path: root/crypto/o_str.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@openssl.org>2024-07-12 16:46:23 +0200
committerTomas Mraz <tomas@openssl.org>2024-07-18 19:07:52 +0200
commit04f7729c409afad235737ee6b4edcb78efdc1bfd (patch)
tree1011818b21a2a9967fa4ea3f27dc5d4c83996f05 /crypto/o_str.c
parentAllow short reads in asn1_d2i_read_bio() (diff)
downloadopenssl-04f7729c409afad235737ee6b4edcb78efdc1bfd.tar.xz
openssl-04f7729c409afad235737ee6b4edcb78efdc1bfd.zip
Add an OPENSSL_strtoul wrapper
utility function to give us sane checking on strtoul conversions Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/24861)
Diffstat (limited to 'crypto/o_str.c')
-rw-r--r--crypto/o_str.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/crypto/o_str.c b/crypto/o_str.c
index dfac215ac3..ba41d76fc1 100644
--- a/crypto/o_str.c
+++ b/crypto/o_str.c
@@ -90,6 +90,74 @@ size_t OPENSSL_strlcat(char *dst, const char *src, size_t size)
return l + OPENSSL_strlcpy(dst, src, size);
}
+/**
+ * @brief Converts a string to an unsigned long integer.
+ *
+ * This function attempts to convert a string representation of a number
+ * to an unsigned long integer, given a specified base. It also provides
+ * error checking and reports whether the conversion was successful.
+ * This function is just a wrapper around the POSIX strtoul function with
+ * additional error checking. This implies that errno for the caller is set
+ * on calls to this function.
+ *
+ * @param str The string containing the representation of the number.
+ * @param endptr A pointer to a pointer to character. If not NULL, it is set
+ * to the character immediately following the number in the
+ * string.
+ * @param base The base to use for the conversion, which must be between 2,
+ * and 36 inclusive, or be the special value 0. If the base is 0,
+ * the actual base is determined by the format of the initial
+ * characters of the string.
+ * @param num A pointer to an unsigned long where the result of the
+ * conversion is stored.
+ *
+ * @return 1 if the conversion was successful, 0 otherwise. Conversion is
+ * considered unsuccessful if no digits were consumed or if an error
+ * occurred during conversion.
+ *
+ * @note It is the caller's responsibility to check if the conversion is
+ * correct based on the expected consumption of the string as reported
+ * by endptr.
+ */
+int OPENSSL_strtoul(const char *str, char **endptr, int base,
+ unsigned long *num)
+{
+ char *tmp_endptr;
+ char **internal_endptr = endptr == NULL ? &tmp_endptr : endptr;
+
+ errno = 0;
+
+ *internal_endptr = (char *)str;
+
+ if (num == NULL)
+ return 0;
+
+ if (str == NULL)
+ return 0;
+
+ /* Fail on negative input */
+ if (*str == '-')
+ return 0;
+
+ *num = strtoul(str, internal_endptr, base);
+ /*
+ * We return error from this function under the following conditions
+ * 1) If strtoul itself returned an error in translation
+ * 2) If the caller didn't pass in an endptr value, and **internal_endptr
+ * doesn't point to '\0'. The implication here is that if the caller
+ * doesn't care how much of a string is consumed, they expect the entire
+ * string to be consumed. As such, no pointing to the NULL terminator
+ * means there was some part of the string left over after translation
+ * 3) If no bytes of the string were consumed
+ */
+ if (errno != 0 ||
+ (endptr == NULL && **internal_endptr != '\0') ||
+ (str == *internal_endptr))
+ return 0;
+
+ return 1;
+}
+
int OPENSSL_hexchar2int(unsigned char c)
{
#ifdef CHARSET_EBCDIC