/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* or 100;100@25;0
* This means 100 mallocs succeed, then next 100 fail 25% of the time, and
* all remaining (count is zero) succeed.
+ * The failure percentge can have 2 digits after the comma. For example:
+ * 0@0.01
+ * This means 0.01% of all allocations will fail.
*/
static void parseit(void)
{
/* Get the count (atol will stop at the @ if there), and percentage */
md_count = atol(md_failstring);
atsign = strchr(md_failstring, '@');
- md_fail_percent = atsign == NULL ? 0 : atoi(atsign + 1);
+ md_fail_percent = atsign == NULL ? 0 : (int)(atof(atsign + 1) * 100 + 0.5);
if (semi != NULL)
md_failstring = semi;
}
/*
- * Windows doesn't have random(), but it has rand()
+ * Windows doesn't have random() and srandom(), but it has rand() and srand().
* Some rand() implementations aren't good, but we're not
* dealing with secure randomness here.
*/
# ifdef _WIN32
# define random() rand()
+# define srandom(seed) srand(seed)
# endif
/*
* See if the current malloc should fail.
*/
static int shouldfail(void)
{
- int roll = (int)(random() % 100);
+ int roll = (int)(random() % 10000);
int shoulditfail = roll < md_fail_percent;
# ifndef _WIN32
/* suppressed on Windows as POSIX-like file descriptors are non-inheritable */
parseit();
if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL)
md_tracefd = atoi(cp);
+ if ((cp = getenv("OPENSSL_MALLOC_SEED")) != NULL)
+ srandom(atoi(cp));
}
#endif
void *ret;
ret = CRYPTO_malloc(num, file, line);
- FAILTEST();
if (ret != NULL)
memset(ret, 0, num);
return ret;
}
+void *CRYPTO_aligned_alloc(size_t num, size_t alignment, void **freeptr,
+ const char *file, int line)
+{
+ void *ret;
+
+ *freeptr = NULL;
+
+#if defined(OPENSSL_SMALL_FOOTPRINT)
+ ret = freeptr = NULL;
+ return ret;
+#endif
+
+#if defined (_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
+ if (posix_memalign(&ret, alignment, num))
+ return NULL;
+ *freeptr = ret;
+ return ret;
+#elif defined(_ISOC11_SOURCE)
+ ret = *freeptr = aligned_alloc(alignment, num);
+ return ret;
+#else
+ /* we have to do this the hard way */
+
+ /*
+ * Note: Windows supports an _aligned_malloc call, but we choose
+ * not to use it here, because allocations from that function
+ * require that they be freed via _aligned_free. Given that
+ * we can't differentiate plain malloc blocks from blocks obtained
+ * via _aligned_malloc, just avoid its use entirely
+ */
+
+ /*
+ * Step 1: Allocate an amount of memory that is <alignment>
+ * bytes bigger than requested
+ */
+ *freeptr = malloc(num + alignment);
+ if (*freeptr == NULL)
+ return NULL;
+
+ /*
+ * Step 2: Add <alignment - 1> bytes to the pointer
+ * This will cross the alignment boundary that is
+ * requested
+ */
+ ret = (void *)((char *)*freeptr + (alignment - 1));
+
+ /*
+ * Step 3: Use the alignment as a mask to translate the
+ * least significant bits of the allocation at the alignment
+ * boundary to 0. ret now holds a pointer to the memory
+ * buffer at the requested alignment
+ * NOTE: It is a documented requirement that alignment be a
+ * power of 2, which is what allows this to work
+ */
+ ret = (void *)((uintptr_t)ret & (uintptr_t)(~(alignment - 1)));
+ return ret;
+#endif
+}
+
void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
{
INCREMENT(realloc_count);
if (realloc_impl != CRYPTO_realloc)
return realloc_impl(str, num, file, line);
- FAILTEST();
if (str == NULL)
return CRYPTO_malloc(num, file, line);
return NULL;
}
+ FAILTEST();
return realloc(str, num);
}