Add test case for overlapping buffers
Signed-off-by: David Horstmann <david.horstmann@arm.com>
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index f27a9be..948196e 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -7458,6 +7458,21 @@
PSA buffers alloc and copy both zero length
psa_crypto_alloc_and_copy_zero_length:1:1
+PSA buffers alloc and copy overlapping input first
+psa_crypto_alloc_and_copy_overlapping:20:20:5:PSA_SUCCESS
+
+PSA buffers alloc and copy overlapping output first
+psa_crypto_alloc_and_copy_overlapping:20:20:-5:PSA_SUCCESS
+
+PSA buffers alloc and copy overlapping output within input
+psa_crypto_alloc_and_copy_overlapping:20:10:5:PSA_SUCCESS
+
+PSA buffers alloc and copy overlapping input within output
+psa_crypto_alloc_and_copy_overlapping:10:20:-5:PSA_SUCCESS
+
+PSA buffers alloc and copy overlapping input equals output
+psa_crypto_alloc_and_copy_overlapping:20:20:0:PSA_SUCCESS
+
PSA buffers copy and free
psa_crypto_copy_and_free:0:20:0:20:0:PSA_SUCCESS
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 4d945c3..600c8ea 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1253,6 +1253,63 @@
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
+/* Helper to get 2 buffers that overlap by the specified amount.
+ * The parameter ptr_diff may be negative, in which case the start of
+ * buf2 is allocated before the start of buf1. */
+static int setup_overlapping_buffers(size_t buf1_len, size_t buf2_len,
+ int ptr_diff,
+ uint8_t **full_buffer,
+ uint8_t **buf1, uint8_t **buf2)
+{
+ size_t total_len;
+ int buf1_offset;
+ int buf2_offset;
+
+ *full_buffer = NULL;
+ *buf1 = NULL;
+ *buf2 = NULL;
+
+ if (ptr_diff >= 0) {
+ /*
+ * |---------- buf1 ----------|
+ * <-- ptr_diff -->|---------- buf2 ----------|
+ */
+ total_len = ptr_diff + buf2_len;
+ if (buf1_len > total_len) {
+ total_len = buf1_len;
+ }
+ buf1_offset = 0;
+ buf2_offset = ptr_diff;
+ } else {
+ /*
+ * <-- (-ptr_diff) -->|---------- buf1 ----------|
+ * |---------- buf2 ----------|
+ */
+ total_len = (-ptr_diff) + buf1_len;
+ if (buf2_len > total_len) {
+ total_len = buf2_len;
+ }
+ buf1_offset = -ptr_diff;
+ buf2_offset = 0;
+ }
+
+ /* Edge case: if the length is zero, allocate a 1-byte buffer to avoid
+ * calloc returning NULL. */
+ if (total_len == 0) {
+ total_len = 1;
+ }
+
+ TEST_CALLOC(*full_buffer, total_len);
+
+ *buf1 = *full_buffer + buf1_offset;
+ *buf2 = *full_buffer + buf2_offset;
+
+ return 0;
+
+exit:
+ return -1;
+}
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -10448,6 +10505,52 @@
/* END_CASE */
/* BEGIN_CASE */
+/* Ensure that overlapping buffers can be copied correctly. */
+void psa_crypto_alloc_and_copy_overlapping(int input_len, int output_len,
+ int ptr_diff, int exp_ret)
+{
+ uint8_t data[] = {0x12, 0x34, 0x56, 0x78};
+ psa_crypto_buffer_copy_t buffer_copies = { 0 };
+
+ uint8_t *full_buffer = NULL;
+ uint8_t *input = NULL;
+ uint8_t *output = NULL;
+
+ psa_status_t ret;
+
+ TEST_EQUAL(setup_overlapping_buffers(input_len, output_len, ptr_diff,
+ &full_buffer, &input, &output), 0);
+
+ for (int i = 0; i < input_len; i++) {
+ input[i] = data[i % sizeof(data)];
+ }
+
+ ret = psa_crypto_alloc_and_copy(input, input_len, output, output_len,
+ &buffer_copies);
+
+ TEST_EQUAL((int) ret, exp_ret);
+
+ if (exp_ret == PSA_SUCCESS) {
+ if (input_len == 0) {
+ TEST_ASSERT(buffer_copies.input == NULL);
+ } else {
+ TEST_MEMORY_COMPARE(input, input_len, buffer_copies.input, buffer_copies.input_len);
+ }
+ if (output_len == 0) {
+ TEST_ASSERT(buffer_copies.output == NULL);
+ } else {
+ TEST_EQUAL(output_len, buffer_copies.output_len);
+ }
+ }
+
+exit:
+ mbedtls_free(full_buffer);
+ mbedtls_free(buffer_copies.input);
+ mbedtls_free(buffer_copies.output);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void psa_crypto_copy_and_free(int input_null, int input_len,
int output_null, int output_len,
int orig_output_null,