mirror of
https://github.com/openssl/openssl.git
synced 2025-01-18 13:44:20 +08:00
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)
This commit is contained in:
parent
202ef97edc
commit
04f7729c40
@ -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
|
||||
|
@ -7,7 +7,7 @@ OPENSSL_malloc, OPENSSL_aligned_alloc, OPENSSL_zalloc, OPENSSL_realloc,
|
||||
OPENSSL_free, OPENSSL_clear_realloc, OPENSSL_clear_free, OPENSSL_cleanse,
|
||||
CRYPTO_malloc, CRYPTO_aligned_alloc, CRYPTO_zalloc, CRYPTO_realloc, CRYPTO_free,
|
||||
OPENSSL_strdup, OPENSSL_strndup,
|
||||
OPENSSL_memdup, OPENSSL_strlcpy, OPENSSL_strlcat,
|
||||
OPENSSL_memdup, OPENSSL_strlcpy, OPENSSL_strlcat, OPENSSL_strtoul,
|
||||
CRYPTO_strdup, CRYPTO_strndup,
|
||||
OPENSSL_mem_debug_push, OPENSSL_mem_debug_pop,
|
||||
CRYPTO_mem_debug_push, CRYPTO_mem_debug_pop,
|
||||
@ -36,6 +36,7 @@ OPENSSL_MALLOC_FD
|
||||
char *OPENSSL_strndup(const char *str, size_t s);
|
||||
size_t OPENSSL_strlcat(char *dst, const char *src, size_t size);
|
||||
size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size);
|
||||
int OPENSSL_strtoul(char *src, char **endptr, int base, unsigned long *num);
|
||||
void *OPENSSL_memdup(void *data, size_t s);
|
||||
void *OPENSSL_clear_realloc(void *p, size_t old_len, size_t num);
|
||||
void OPENSSL_clear_free(void *str, size_t num);
|
||||
@ -135,6 +136,12 @@ OPENSSL_strlcpy(),
|
||||
OPENSSL_strlcat() and OPENSSL_strnlen() are equivalents of the common C
|
||||
library functions and are provided for portability.
|
||||
|
||||
OPENSSL_strtoul() is a wrapper around the POSIX function strtoul, with the same
|
||||
behaviors listed in the POSIX documentation, with the additional behavior that
|
||||
it validates the input I<str> and I<num> parameters for not being NULL, and confirms
|
||||
that at least a single byte of input has been consumed in the translation,
|
||||
returning an error in the event that no bytes were consumed.
|
||||
|
||||
If no allocations have been done, it is possible to "swap out" the default
|
||||
implementations for OPENSSL_malloc(), OPENSSL_realloc() and OPENSSL_free()
|
||||
and replace them with alternate versions.
|
||||
@ -203,6 +210,35 @@ OPENSSL_mem_debug_push(), OPENSSL_mem_debug_pop(),
|
||||
CRYPTO_mem_debug_push(), and CRYPTO_mem_debug_pop()
|
||||
are deprecated and are no-ops that always return 0.
|
||||
|
||||
OPENSSL_strtoul() returns 1 on success and 0 in the event that an error has
|
||||
occured. Specifically, 0 is returned in the following events:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
If the underlying call to strtoul returned a non zero errno value
|
||||
|
||||
=item *
|
||||
|
||||
If the translation did not consume the entire input string, and the passed
|
||||
endptr value was NULL
|
||||
|
||||
=item *
|
||||
|
||||
If no characters were consumed in the translation
|
||||
|
||||
=back
|
||||
|
||||
Note that a success condition does not imply that the expected
|
||||
translation has been preformed. For instance calling
|
||||
|
||||
OPENSSL_strtoul("0x12345", &endptr, 10, &num);
|
||||
|
||||
will result in a successful translation with num having the value 0, and
|
||||
*endptr = 'x'. Be sure to validate how much data was consumed when calling this
|
||||
function.
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
OPENSSL_mem_debug_push(), OPENSSL_mem_debug_pop(),
|
||||
|
@ -134,6 +134,7 @@ int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock);
|
||||
size_t OPENSSL_strlcpy(char *dst, const char *src, size_t siz);
|
||||
size_t OPENSSL_strlcat(char *dst, const char *src, size_t siz);
|
||||
size_t OPENSSL_strnlen(const char *str, size_t maxlen);
|
||||
int OPENSSL_strtoul(const char *str, char **endptr, int base, unsigned long *num);
|
||||
int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlength,
|
||||
const unsigned char *buf, size_t buflen,
|
||||
const char sep);
|
||||
|
@ -5702,3 +5702,4 @@ OSSL_USER_NOTICE_SYNTAX_new ? 3_4_0 EXIST::FUNCTION:
|
||||
OSSL_USER_NOTICE_SYNTAX_it ? 3_4_0 EXIST::FUNCTION:
|
||||
OSSL_INDICATOR_set_callback ? 3_4_0 EXIST::FUNCTION:
|
||||
OSSL_INDICATOR_get_callback ? 3_4_0 EXIST::FUNCTION:
|
||||
OPENSSL_strtoul ? 3_4_0 EXIST::FUNCTION:
|
||||
|
Loading…
Reference in New Issue
Block a user