Use sdallocx, if available, when deallocating.
Providing a size hint to the allocator is substantially faster,
especially as we already know/need the size for OPENSSL_cleanse.
We provide a weak symbol that falls back to free when a malloc with
sdallocx is not statically linked with BoringSSL.
Alternatives considered:
* Use dlsym(): This is prone to fail on statically linked binaries
without symbols. Additionally, the extra indirection adds call
overhead above and beyond the linker resolved technique we're using.
* Use CMake rules to identify whether sdallocx is available: Once the
library is built, we may link against a variety of malloc
implementations (not all of which may have sdallocx), so we need to
have a fallback when the symbol is unavailable.
Change-Id: I3a78e88fac5b6e5d4712aa0347d2ba6b43046e07
Reviewed-on: https://boringssl-review.googlesource.com/31784
Reviewed-by: Chris Kennelly <ckennelly@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/mem.c b/crypto/mem.c
index 5d45baa..a06061b 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -71,6 +71,25 @@
#define OPENSSL_MALLOC_PREFIX 8
+#if defined(__GNUC__) || defined(__clang__)
+// sdallocx is a sized |free| function. By passing the size (which we happen to
+// always know in BoringSSL), the malloc implementation can save work. We cannot
+// depend on |sdallocx| being available so we declare a wrapper that falls back
+// to |free| as a weak symbol.
+//
+// This will always be safe, but will only be overridden if the malloc
+// implementation is statically linked with BoringSSL. So, if |sdallocx| is
+// provided in, say, libc.so, we still won't use it because that's dynamically
+// linked. This isn't an ideal result, but its helps in some cases.
+void sdallocx(void *ptr, size_t size, int flags);
+
+__attribute((weak, noinline))
+#else
+static
+#endif
+void sdallocx(void *ptr, size_t size, int flags) {
+ free(ptr);
+}
void *OPENSSL_malloc(size_t size) {
void *ptr = malloc(size + OPENSSL_MALLOC_PREFIX);
@@ -92,7 +111,7 @@
size_t size = *(size_t *)ptr;
OPENSSL_cleanse(ptr, size + OPENSSL_MALLOC_PREFIX);
- free(ptr);
+ sdallocx(ptr, size + OPENSSL_MALLOC_PREFIX, 0 /* flags */);
}
void *OPENSSL_realloc(void *orig_ptr, size_t new_size) {