Add OPENSSL_asprintf and friends for asprintf(3) functionality.
This includes an internal version which allows a flag to specify the use of system malloc, or OPENSSL_malloc - this in turn allows us to use this function in the ERR family of functions and allow for ERR to not call OPENSSL_malloc with a circular dependency. Bug: 564 Change-Id: Ifd02d062fda9695cddbb0dbef2e1c1db0802a486 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57005 Auto-Submit: Bob Beck <bbe@google.com> Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: Bob Beck <bbe@google.com>
This commit is contained in:
parent
ace3316154
commit
350f8547cf
@ -1299,6 +1299,13 @@ OPENSSL_INLINE int CRYPTO_is_ARMv8_PMULL_capable(void) {
|
||||
extern uint8_t BORINGSSL_function_hit[7];
|
||||
#endif // BORINGSSL_DISPATCH_TEST
|
||||
|
||||
// OPENSSL_vasprintf_internal is just like |vasprintf(3)|. if |system_malloc| is
|
||||
// 0, memory will be allocated with |OPENSSL_malloc| and must be freed with
|
||||
// |OPENSSL_free|. Otherwise the system |malloc| function is used and the memory
|
||||
// must be freed with the system |free| function.
|
||||
OPENSSL_EXPORT int OPENSSL_vasprintf_internal(char **str, const char *format,
|
||||
va_list args, int system_malloc)
|
||||
OPENSSL_PRINTF_FORMAT_FUNC(2, 0);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern C
|
||||
|
98
crypto/mem.c
98
crypto/mem.c
@ -57,9 +57,11 @@
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
@ -127,7 +129,7 @@ WEAK_SYMBOL_FUNC(void, sdallocx, (void *ptr, size_t size, int flags));
|
||||
// primitives used must tolerate every other synchronization primitive linked
|
||||
// into the process, including pthreads locks. Failing to meet these constraints
|
||||
// may result in deadlocks, crashes, or memory corruption.
|
||||
WEAK_SYMBOL_FUNC(void*, OPENSSL_memory_alloc, (size_t size));
|
||||
WEAK_SYMBOL_FUNC(void *, OPENSSL_memory_alloc, (size_t size));
|
||||
WEAK_SYMBOL_FUNC(void, OPENSSL_memory_free, (void *ptr));
|
||||
WEAK_SYMBOL_FUNC(size_t, OPENSSL_memory_get_size, (void *ptr));
|
||||
|
||||
@ -135,10 +137,25 @@ WEAK_SYMBOL_FUNC(size_t, OPENSSL_memory_get_size, (void *ptr));
|
||||
// are linking in BoringSSL and, roughly, what version they are using.
|
||||
static const uint8_t kBoringSSLBinaryTag[18] = {
|
||||
// 16 bytes of magic tag.
|
||||
0x8c, 0x62, 0x20, 0x0b, 0xd2, 0xa0, 0x72, 0x58,
|
||||
0x44, 0xa8, 0x96, 0x69, 0xad, 0x55, 0x7e, 0xec,
|
||||
0x8c,
|
||||
0x62,
|
||||
0x20,
|
||||
0x0b,
|
||||
0xd2,
|
||||
0xa0,
|
||||
0x72,
|
||||
0x58,
|
||||
0x44,
|
||||
0xa8,
|
||||
0x96,
|
||||
0x69,
|
||||
0xad,
|
||||
0x55,
|
||||
0x7e,
|
||||
0xec,
|
||||
// Current source iteration. Incremented ~monthly.
|
||||
3, 0,
|
||||
3,
|
||||
0,
|
||||
};
|
||||
|
||||
#if defined(BORINGSSL_MALLOC_FAILURE_TESTING)
|
||||
@ -321,9 +338,7 @@ void OPENSSL_cleanse(void *ptr, size_t len) {
|
||||
#endif // !OPENSSL_NO_ASM
|
||||
}
|
||||
|
||||
void OPENSSL_clear_free(void *ptr, size_t unused) {
|
||||
OPENSSL_free(ptr);
|
||||
}
|
||||
void OPENSSL_clear_free(void *ptr, size_t unused) { OPENSSL_free(ptr); }
|
||||
|
||||
int CRYPTO_secure_malloc_init(size_t size, size_t min_size) { return 0; }
|
||||
|
||||
@ -394,9 +409,7 @@ int OPENSSL_isalpha(int c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
int OPENSSL_isdigit(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
int OPENSSL_isdigit(int c) { return c >= '0' && c <= '9'; }
|
||||
|
||||
int OPENSSL_isxdigit(int c) {
|
||||
return OPENSSL_isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
@ -418,9 +431,7 @@ int OPENSSL_fromxdigit(uint8_t *out, int c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OPENSSL_isalnum(int c) {
|
||||
return OPENSSL_isalpha(c) || OPENSSL_isdigit(c);
|
||||
}
|
||||
int OPENSSL_isalnum(int c) { return OPENSSL_isalpha(c) || OPENSSL_isdigit(c); }
|
||||
|
||||
int OPENSSL_tolower(int c) {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
@ -478,6 +489,65 @@ int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) {
|
||||
return vsnprintf(buf, n, format, args);
|
||||
}
|
||||
|
||||
int OPENSSL_vasprintf_internal(char **str, const char *format, va_list args,
|
||||
int system_malloc) {
|
||||
void *(*allocate)(size_t) = system_malloc ? malloc : OPENSSL_malloc;
|
||||
void (*deallocate)(void *) = system_malloc ? free : OPENSSL_free;
|
||||
void *(*reallocate)(void *, size_t) =
|
||||
system_malloc ? realloc : OPENSSL_realloc;
|
||||
char *candidate = NULL;
|
||||
size_t candidate_len = 64; // TODO(bbe) what's the best initial size?
|
||||
|
||||
if ((candidate = allocate(candidate_len)) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
int ret = vsnprintf(candidate, candidate_len, format, args_copy);
|
||||
va_end(args_copy);
|
||||
if (ret == INT_MAX || ret < 0) {
|
||||
// Failed, or size not int representable.
|
||||
goto err;
|
||||
}
|
||||
if ((size_t)ret >= candidate_len) {
|
||||
// Too big to fit in allocation.
|
||||
char *tmp;
|
||||
|
||||
candidate_len = ret + 1;
|
||||
if ((tmp = reallocate(candidate, candidate_len)) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
candidate = tmp;
|
||||
va_copy(args_copy, args);
|
||||
ret = vsnprintf(candidate, candidate_len, format, args_copy);
|
||||
va_end(args_copy);
|
||||
}
|
||||
// At this point this can't happen unless vsnprintf is insane.
|
||||
if (ret < 0 || (size_t)ret >= candidate_len) {
|
||||
goto err;
|
||||
}
|
||||
*str = candidate;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
deallocate(candidate);
|
||||
*str = NULL;
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int OPENSSL_vasprintf(char **str, const char *format, va_list args) {
|
||||
return OPENSSL_vasprintf_internal(str, format, args, /*system_malloc=*/0);
|
||||
}
|
||||
|
||||
int OPENSSL_asprintf(char **str, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = OPENSSL_vasprintf(str, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *OPENSSL_strndup(const char *str, size_t size) {
|
||||
size = OPENSSL_strnlen(str, size);
|
||||
|
||||
|
@ -84,7 +84,8 @@ OPENSSL_EXPORT void OPENSSL_free(void *ptr);
|
||||
|
||||
// OPENSSL_realloc returns a pointer to a buffer of |new_size| bytes that
|
||||
// contains the contents of |ptr|. Unlike |realloc|, a new buffer is always
|
||||
// allocated and the data at |ptr| is always wiped and freed.
|
||||
// allocated and the data at |ptr| is always wiped and freed. Memory is
|
||||
// allocated with |OPENSSL_malloc| and must be freed with |OPENSSL_free|.
|
||||
OPENSSL_EXPORT void *OPENSSL_realloc(void *ptr, size_t new_size);
|
||||
|
||||
// OPENSSL_cleanse zeros out |len| bytes of memory at |ptr|. This is similar to
|
||||
@ -160,12 +161,25 @@ OPENSSL_EXPORT int BIO_snprintf(char *buf, size_t n, const char *format, ...)
|
||||
OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format,
|
||||
va_list args) OPENSSL_PRINTF_FORMAT_FUNC(3, 0);
|
||||
|
||||
// OPENSSL_vasprintf has the same behavior as vasprintf(3), except that
|
||||
// memory allocated in a returned string must be freed with |OPENSSL_free|.
|
||||
OPENSSL_EXPORT int OPENSSL_vasprintf(char **str, const char *format,
|
||||
va_list args)
|
||||
OPENSSL_PRINTF_FORMAT_FUNC(2, 0);
|
||||
|
||||
// OPENSSL_asprintf has the same behavior as asprintf(3), except that
|
||||
// memory allocated in a returned string must be freed with |OPENSSL_free|.
|
||||
OPENSSL_EXPORT int OPENSSL_asprintf(char **str, const char *format, ...)
|
||||
OPENSSL_PRINTF_FORMAT_FUNC(2, 3);
|
||||
|
||||
// OPENSSL_strndup returns an allocated, duplicate of |str|, which is, at most,
|
||||
// |size| bytes. The result is always NUL terminated.
|
||||
// |size| bytes. The result is always NUL terminated. The memory allocated
|
||||
// must be freed with |OPENSSL_free|.
|
||||
OPENSSL_EXPORT char *OPENSSL_strndup(const char *str, size_t size);
|
||||
|
||||
// OPENSSL_memdup returns an allocated, duplicate of |size| bytes from |data| or
|
||||
// NULL on allocation failure.
|
||||
// NULL on allocation failure. The memory allocated must be freed with
|
||||
// |OPENSSL_free|.
|
||||
OPENSSL_EXPORT void *OPENSSL_memdup(const void *data, size_t size);
|
||||
|
||||
// OPENSSL_strlcpy acts like strlcpy(3).
|
||||
|
Loading…
x
Reference in New Issue
Block a user