diff options
author | Neil Horman <nhorman@openssl.org> | 2024-07-12 16:46:23 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2024-07-18 19:07:52 +0200 |
commit | 04f7729c409afad235737ee6b4edcb78efdc1bfd (patch) | |
tree | 1011818b21a2a9967fa4ea3f27dc5d4c83996f05 /crypto/o_str.c | |
parent | Allow short reads in asn1_d2i_read_bio() (diff) | |
download | openssl-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.c | 68 |
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 |