1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  Buffer-based memory allocator
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
5a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0
6a8e1175bSopenharmony_ci *
7a8e1175bSopenharmony_ci *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8a8e1175bSopenharmony_ci *  not use this file except in compliance with the License.
9a8e1175bSopenharmony_ci *  You may obtain a copy of the License at
10a8e1175bSopenharmony_ci *
11a8e1175bSopenharmony_ci *  http://www.apache.org/licenses/LICENSE-2.0
12a8e1175bSopenharmony_ci *
13a8e1175bSopenharmony_ci *  Unless required by applicable law or agreed to in writing, software
14a8e1175bSopenharmony_ci *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15a8e1175bSopenharmony_ci *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16a8e1175bSopenharmony_ci *  See the License for the specific language governing permissions and
17a8e1175bSopenharmony_ci *  limitations under the License.
18a8e1175bSopenharmony_ci */
19a8e1175bSopenharmony_ci
20a8e1175bSopenharmony_ci#include "common.h"
21a8e1175bSopenharmony_ci
22a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
23a8e1175bSopenharmony_ci#include "mbedtls/memory_buffer_alloc.h"
24a8e1175bSopenharmony_ci
25a8e1175bSopenharmony_ci/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
26a8e1175bSopenharmony_ci   is dependent upon MBEDTLS_PLATFORM_C */
27a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
28a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h"
29a8e1175bSopenharmony_ci
30a8e1175bSopenharmony_ci#include <string.h>
31a8e1175bSopenharmony_ci
32a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
33a8e1175bSopenharmony_ci#include <execinfo.h>
34a8e1175bSopenharmony_ci#endif
35a8e1175bSopenharmony_ci
36a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
37a8e1175bSopenharmony_ci#include "mbedtls/threading.h"
38a8e1175bSopenharmony_ci#endif
39a8e1175bSopenharmony_ci
40a8e1175bSopenharmony_ci#define MAGIC1       0xFF00AA55
41a8e1175bSopenharmony_ci#define MAGIC2       0xEE119966
42a8e1175bSopenharmony_ci#define MAX_BT 20
43a8e1175bSopenharmony_ci
44a8e1175bSopenharmony_citypedef struct _memory_header memory_header;
45a8e1175bSopenharmony_cistruct _memory_header {
46a8e1175bSopenharmony_ci    size_t          magic1;
47a8e1175bSopenharmony_ci    size_t          size;
48a8e1175bSopenharmony_ci    size_t          alloc;
49a8e1175bSopenharmony_ci    memory_header   *prev;
50a8e1175bSopenharmony_ci    memory_header   *next;
51a8e1175bSopenharmony_ci    memory_header   *prev_free;
52a8e1175bSopenharmony_ci    memory_header   *next_free;
53a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
54a8e1175bSopenharmony_ci    char            **trace;
55a8e1175bSopenharmony_ci    size_t          trace_count;
56a8e1175bSopenharmony_ci#endif
57a8e1175bSopenharmony_ci    size_t          magic2;
58a8e1175bSopenharmony_ci};
59a8e1175bSopenharmony_ci
60a8e1175bSopenharmony_citypedef struct {
61a8e1175bSopenharmony_ci    unsigned char   *buf;
62a8e1175bSopenharmony_ci    size_t          len;
63a8e1175bSopenharmony_ci    memory_header   *first;
64a8e1175bSopenharmony_ci    memory_header   *first_free;
65a8e1175bSopenharmony_ci    int             verify;
66a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
67a8e1175bSopenharmony_ci    size_t          alloc_count;
68a8e1175bSopenharmony_ci    size_t          free_count;
69a8e1175bSopenharmony_ci    size_t          total_used;
70a8e1175bSopenharmony_ci    size_t          maximum_used;
71a8e1175bSopenharmony_ci    size_t          header_count;
72a8e1175bSopenharmony_ci    size_t          maximum_header_count;
73a8e1175bSopenharmony_ci#endif
74a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
75a8e1175bSopenharmony_ci    mbedtls_threading_mutex_t   mutex;
76a8e1175bSopenharmony_ci#endif
77a8e1175bSopenharmony_ci}
78a8e1175bSopenharmony_cibuffer_alloc_ctx;
79a8e1175bSopenharmony_ci
80a8e1175bSopenharmony_cistatic buffer_alloc_ctx heap;
81a8e1175bSopenharmony_ci
82a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
83a8e1175bSopenharmony_cistatic void debug_header(memory_header *hdr)
84a8e1175bSopenharmony_ci{
85a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
86a8e1175bSopenharmony_ci    size_t i;
87a8e1175bSopenharmony_ci#endif
88a8e1175bSopenharmony_ci
89a8e1175bSopenharmony_ci    mbedtls_fprintf(stderr, "HDR:  PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
90a8e1175bSopenharmony_ci                            "ALLOC(%zu), SIZE(%10zu)\n",
91a8e1175bSopenharmony_ci                    (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
92a8e1175bSopenharmony_ci                    hdr->alloc, hdr->size);
93a8e1175bSopenharmony_ci    mbedtls_fprintf(stderr, "      FPREV(%10zu), FNEXT(%10zu)\n",
94a8e1175bSopenharmony_ci                    (size_t) hdr->prev_free, (size_t) hdr->next_free);
95a8e1175bSopenharmony_ci
96a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
97a8e1175bSopenharmony_ci    mbedtls_fprintf(stderr, "TRACE: \n");
98a8e1175bSopenharmony_ci    for (i = 0; i < hdr->trace_count; i++) {
99a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "%s\n", hdr->trace[i]);
100a8e1175bSopenharmony_ci    }
101a8e1175bSopenharmony_ci    mbedtls_fprintf(stderr, "\n");
102a8e1175bSopenharmony_ci#endif
103a8e1175bSopenharmony_ci}
104a8e1175bSopenharmony_ci
105a8e1175bSopenharmony_cistatic void debug_chain(void)
106a8e1175bSopenharmony_ci{
107a8e1175bSopenharmony_ci    memory_header *cur = heap.first;
108a8e1175bSopenharmony_ci
109a8e1175bSopenharmony_ci    mbedtls_fprintf(stderr, "\nBlock list\n");
110a8e1175bSopenharmony_ci    while (cur != NULL) {
111a8e1175bSopenharmony_ci        debug_header(cur);
112a8e1175bSopenharmony_ci        cur = cur->next;
113a8e1175bSopenharmony_ci    }
114a8e1175bSopenharmony_ci
115a8e1175bSopenharmony_ci    mbedtls_fprintf(stderr, "Free list\n");
116a8e1175bSopenharmony_ci    cur = heap.first_free;
117a8e1175bSopenharmony_ci
118a8e1175bSopenharmony_ci    while (cur != NULL) {
119a8e1175bSopenharmony_ci        debug_header(cur);
120a8e1175bSopenharmony_ci        cur = cur->next_free;
121a8e1175bSopenharmony_ci    }
122a8e1175bSopenharmony_ci}
123a8e1175bSopenharmony_ci#endif /* MBEDTLS_MEMORY_DEBUG */
124a8e1175bSopenharmony_ci
125a8e1175bSopenharmony_cistatic int verify_header(memory_header *hdr)
126a8e1175bSopenharmony_ci{
127a8e1175bSopenharmony_ci    if (hdr->magic1 != MAGIC1) {
128a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
129a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: MAGIC1 mismatch\n");
130a8e1175bSopenharmony_ci#endif
131a8e1175bSopenharmony_ci        return 1;
132a8e1175bSopenharmony_ci    }
133a8e1175bSopenharmony_ci
134a8e1175bSopenharmony_ci    if (hdr->magic2 != MAGIC2) {
135a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
136a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: MAGIC2 mismatch\n");
137a8e1175bSopenharmony_ci#endif
138a8e1175bSopenharmony_ci        return 1;
139a8e1175bSopenharmony_ci    }
140a8e1175bSopenharmony_ci
141a8e1175bSopenharmony_ci    if (hdr->alloc > 1) {
142a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
143a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: alloc has illegal value\n");
144a8e1175bSopenharmony_ci#endif
145a8e1175bSopenharmony_ci        return 1;
146a8e1175bSopenharmony_ci    }
147a8e1175bSopenharmony_ci
148a8e1175bSopenharmony_ci    if (hdr->prev != NULL && hdr->prev == hdr->next) {
149a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
150a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: prev == next\n");
151a8e1175bSopenharmony_ci#endif
152a8e1175bSopenharmony_ci        return 1;
153a8e1175bSopenharmony_ci    }
154a8e1175bSopenharmony_ci
155a8e1175bSopenharmony_ci    if (hdr->prev_free != NULL && hdr->prev_free == hdr->next_free) {
156a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
157a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: prev_free == next_free\n");
158a8e1175bSopenharmony_ci#endif
159a8e1175bSopenharmony_ci        return 1;
160a8e1175bSopenharmony_ci    }
161a8e1175bSopenharmony_ci
162a8e1175bSopenharmony_ci    return 0;
163a8e1175bSopenharmony_ci}
164a8e1175bSopenharmony_ci
165a8e1175bSopenharmony_cistatic int verify_chain(void)
166a8e1175bSopenharmony_ci{
167a8e1175bSopenharmony_ci    memory_header *prv = heap.first, *cur;
168a8e1175bSopenharmony_ci
169a8e1175bSopenharmony_ci    if (prv == NULL || verify_header(prv) != 0) {
170a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
171a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: verification of first header "
172a8e1175bSopenharmony_ci                                "failed\n");
173a8e1175bSopenharmony_ci#endif
174a8e1175bSopenharmony_ci        return 1;
175a8e1175bSopenharmony_ci    }
176a8e1175bSopenharmony_ci
177a8e1175bSopenharmony_ci    if (heap.first->prev != NULL) {
178a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
179a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: verification failed: "
180a8e1175bSopenharmony_ci                                "first->prev != NULL\n");
181a8e1175bSopenharmony_ci#endif
182a8e1175bSopenharmony_ci        return 1;
183a8e1175bSopenharmony_ci    }
184a8e1175bSopenharmony_ci
185a8e1175bSopenharmony_ci    cur = heap.first->next;
186a8e1175bSopenharmony_ci
187a8e1175bSopenharmony_ci    while (cur != NULL) {
188a8e1175bSopenharmony_ci        if (verify_header(cur) != 0) {
189a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
190a8e1175bSopenharmony_ci            mbedtls_fprintf(stderr, "FATAL: verification of header "
191a8e1175bSopenharmony_ci                                    "failed\n");
192a8e1175bSopenharmony_ci#endif
193a8e1175bSopenharmony_ci            return 1;
194a8e1175bSopenharmony_ci        }
195a8e1175bSopenharmony_ci
196a8e1175bSopenharmony_ci        if (cur->prev != prv) {
197a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
198a8e1175bSopenharmony_ci            mbedtls_fprintf(stderr, "FATAL: verification failed: "
199a8e1175bSopenharmony_ci                                    "cur->prev != prv\n");
200a8e1175bSopenharmony_ci#endif
201a8e1175bSopenharmony_ci            return 1;
202a8e1175bSopenharmony_ci        }
203a8e1175bSopenharmony_ci
204a8e1175bSopenharmony_ci        prv = cur;
205a8e1175bSopenharmony_ci        cur = cur->next;
206a8e1175bSopenharmony_ci    }
207a8e1175bSopenharmony_ci
208a8e1175bSopenharmony_ci    return 0;
209a8e1175bSopenharmony_ci}
210a8e1175bSopenharmony_ci
211a8e1175bSopenharmony_cistatic void *buffer_alloc_calloc(size_t n, size_t size)
212a8e1175bSopenharmony_ci{
213a8e1175bSopenharmony_ci    memory_header *new, *cur = heap.first_free;
214a8e1175bSopenharmony_ci    unsigned char *p;
215a8e1175bSopenharmony_ci    void *ret;
216a8e1175bSopenharmony_ci    size_t original_len, len;
217a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
218a8e1175bSopenharmony_ci    void *trace_buffer[MAX_BT];
219a8e1175bSopenharmony_ci    size_t trace_cnt;
220a8e1175bSopenharmony_ci#endif
221a8e1175bSopenharmony_ci
222a8e1175bSopenharmony_ci    if (heap.buf == NULL || heap.first == NULL) {
223a8e1175bSopenharmony_ci        return NULL;
224a8e1175bSopenharmony_ci    }
225a8e1175bSopenharmony_ci
226a8e1175bSopenharmony_ci    original_len = len = n * size;
227a8e1175bSopenharmony_ci
228a8e1175bSopenharmony_ci    if (n == 0 || size == 0 || len / n != size) {
229a8e1175bSopenharmony_ci        return NULL;
230a8e1175bSopenharmony_ci    } else if (len > (size_t) -MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
231a8e1175bSopenharmony_ci        return NULL;
232a8e1175bSopenharmony_ci    }
233a8e1175bSopenharmony_ci
234a8e1175bSopenharmony_ci    if (len % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
235a8e1175bSopenharmony_ci        len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
236a8e1175bSopenharmony_ci        len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
237a8e1175bSopenharmony_ci    }
238a8e1175bSopenharmony_ci
239a8e1175bSopenharmony_ci    // Find block that fits
240a8e1175bSopenharmony_ci    //
241a8e1175bSopenharmony_ci    while (cur != NULL) {
242a8e1175bSopenharmony_ci        if (cur->size >= len) {
243a8e1175bSopenharmony_ci            break;
244a8e1175bSopenharmony_ci        }
245a8e1175bSopenharmony_ci
246a8e1175bSopenharmony_ci        cur = cur->next_free;
247a8e1175bSopenharmony_ci    }
248a8e1175bSopenharmony_ci
249a8e1175bSopenharmony_ci    if (cur == NULL) {
250a8e1175bSopenharmony_ci        return NULL;
251a8e1175bSopenharmony_ci    }
252a8e1175bSopenharmony_ci
253a8e1175bSopenharmony_ci    if (cur->alloc != 0) {
254a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
255a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: block in free_list but allocated "
256a8e1175bSopenharmony_ci                                "data\n");
257a8e1175bSopenharmony_ci#endif
258a8e1175bSopenharmony_ci        mbedtls_exit(1);
259a8e1175bSopenharmony_ci    }
260a8e1175bSopenharmony_ci
261a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
262a8e1175bSopenharmony_ci    heap.alloc_count++;
263a8e1175bSopenharmony_ci#endif
264a8e1175bSopenharmony_ci
265a8e1175bSopenharmony_ci    // Found location, split block if > memory_header + 4 room left
266a8e1175bSopenharmony_ci    //
267a8e1175bSopenharmony_ci    if (cur->size - len < sizeof(memory_header) +
268a8e1175bSopenharmony_ci        MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
269a8e1175bSopenharmony_ci        cur->alloc = 1;
270a8e1175bSopenharmony_ci
271a8e1175bSopenharmony_ci        // Remove from free_list
272a8e1175bSopenharmony_ci        //
273a8e1175bSopenharmony_ci        if (cur->prev_free != NULL) {
274a8e1175bSopenharmony_ci            cur->prev_free->next_free = cur->next_free;
275a8e1175bSopenharmony_ci        } else {
276a8e1175bSopenharmony_ci            heap.first_free = cur->next_free;
277a8e1175bSopenharmony_ci        }
278a8e1175bSopenharmony_ci
279a8e1175bSopenharmony_ci        if (cur->next_free != NULL) {
280a8e1175bSopenharmony_ci            cur->next_free->prev_free = cur->prev_free;
281a8e1175bSopenharmony_ci        }
282a8e1175bSopenharmony_ci
283a8e1175bSopenharmony_ci        cur->prev_free = NULL;
284a8e1175bSopenharmony_ci        cur->next_free = NULL;
285a8e1175bSopenharmony_ci
286a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
287a8e1175bSopenharmony_ci        heap.total_used += cur->size;
288a8e1175bSopenharmony_ci        if (heap.total_used > heap.maximum_used) {
289a8e1175bSopenharmony_ci            heap.maximum_used = heap.total_used;
290a8e1175bSopenharmony_ci        }
291a8e1175bSopenharmony_ci#endif
292a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
293a8e1175bSopenharmony_ci        trace_cnt = backtrace(trace_buffer, MAX_BT);
294a8e1175bSopenharmony_ci        cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
295a8e1175bSopenharmony_ci        cur->trace_count = trace_cnt;
296a8e1175bSopenharmony_ci#endif
297a8e1175bSopenharmony_ci
298a8e1175bSopenharmony_ci        if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
299a8e1175bSopenharmony_ci            mbedtls_exit(1);
300a8e1175bSopenharmony_ci        }
301a8e1175bSopenharmony_ci
302a8e1175bSopenharmony_ci        ret = (unsigned char *) cur + sizeof(memory_header);
303a8e1175bSopenharmony_ci        memset(ret, 0, original_len);
304a8e1175bSopenharmony_ci
305a8e1175bSopenharmony_ci        return ret;
306a8e1175bSopenharmony_ci    }
307a8e1175bSopenharmony_ci
308a8e1175bSopenharmony_ci    p = ((unsigned char *) cur) + sizeof(memory_header) + len;
309a8e1175bSopenharmony_ci    new = (memory_header *) p;
310a8e1175bSopenharmony_ci
311a8e1175bSopenharmony_ci    new->size = cur->size - len - sizeof(memory_header);
312a8e1175bSopenharmony_ci    new->alloc = 0;
313a8e1175bSopenharmony_ci    new->prev = cur;
314a8e1175bSopenharmony_ci    new->next = cur->next;
315a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
316a8e1175bSopenharmony_ci    new->trace = NULL;
317a8e1175bSopenharmony_ci    new->trace_count = 0;
318a8e1175bSopenharmony_ci#endif
319a8e1175bSopenharmony_ci    new->magic1 = MAGIC1;
320a8e1175bSopenharmony_ci    new->magic2 = MAGIC2;
321a8e1175bSopenharmony_ci
322a8e1175bSopenharmony_ci    if (new->next != NULL) {
323a8e1175bSopenharmony_ci        new->next->prev = new;
324a8e1175bSopenharmony_ci    }
325a8e1175bSopenharmony_ci
326a8e1175bSopenharmony_ci    // Replace cur with new in free_list
327a8e1175bSopenharmony_ci    //
328a8e1175bSopenharmony_ci    new->prev_free = cur->prev_free;
329a8e1175bSopenharmony_ci    new->next_free = cur->next_free;
330a8e1175bSopenharmony_ci    if (new->prev_free != NULL) {
331a8e1175bSopenharmony_ci        new->prev_free->next_free = new;
332a8e1175bSopenharmony_ci    } else {
333a8e1175bSopenharmony_ci        heap.first_free = new;
334a8e1175bSopenharmony_ci    }
335a8e1175bSopenharmony_ci
336a8e1175bSopenharmony_ci    if (new->next_free != NULL) {
337a8e1175bSopenharmony_ci        new->next_free->prev_free = new;
338a8e1175bSopenharmony_ci    }
339a8e1175bSopenharmony_ci
340a8e1175bSopenharmony_ci    cur->alloc = 1;
341a8e1175bSopenharmony_ci    cur->size = len;
342a8e1175bSopenharmony_ci    cur->next = new;
343a8e1175bSopenharmony_ci    cur->prev_free = NULL;
344a8e1175bSopenharmony_ci    cur->next_free = NULL;
345a8e1175bSopenharmony_ci
346a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
347a8e1175bSopenharmony_ci    heap.header_count++;
348a8e1175bSopenharmony_ci    if (heap.header_count > heap.maximum_header_count) {
349a8e1175bSopenharmony_ci        heap.maximum_header_count = heap.header_count;
350a8e1175bSopenharmony_ci    }
351a8e1175bSopenharmony_ci    heap.total_used += cur->size;
352a8e1175bSopenharmony_ci    if (heap.total_used > heap.maximum_used) {
353a8e1175bSopenharmony_ci        heap.maximum_used = heap.total_used;
354a8e1175bSopenharmony_ci    }
355a8e1175bSopenharmony_ci#endif
356a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
357a8e1175bSopenharmony_ci    trace_cnt = backtrace(trace_buffer, MAX_BT);
358a8e1175bSopenharmony_ci    cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
359a8e1175bSopenharmony_ci    cur->trace_count = trace_cnt;
360a8e1175bSopenharmony_ci#endif
361a8e1175bSopenharmony_ci
362a8e1175bSopenharmony_ci    if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
363a8e1175bSopenharmony_ci        mbedtls_exit(1);
364a8e1175bSopenharmony_ci    }
365a8e1175bSopenharmony_ci
366a8e1175bSopenharmony_ci    ret = (unsigned char *) cur + sizeof(memory_header);
367a8e1175bSopenharmony_ci    memset(ret, 0, original_len);
368a8e1175bSopenharmony_ci
369a8e1175bSopenharmony_ci    return ret;
370a8e1175bSopenharmony_ci}
371a8e1175bSopenharmony_ci
372a8e1175bSopenharmony_cistatic void buffer_alloc_free(void *ptr)
373a8e1175bSopenharmony_ci{
374a8e1175bSopenharmony_ci    memory_header *hdr, *old = NULL;
375a8e1175bSopenharmony_ci    unsigned char *p = (unsigned char *) ptr;
376a8e1175bSopenharmony_ci
377a8e1175bSopenharmony_ci    if (ptr == NULL || heap.buf == NULL || heap.first == NULL) {
378a8e1175bSopenharmony_ci        return;
379a8e1175bSopenharmony_ci    }
380a8e1175bSopenharmony_ci
381a8e1175bSopenharmony_ci    if (p < heap.buf || p >= heap.buf + heap.len) {
382a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
383a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: mbedtls_free() outside of managed "
384a8e1175bSopenharmony_ci                                "space\n");
385a8e1175bSopenharmony_ci#endif
386a8e1175bSopenharmony_ci        mbedtls_exit(1);
387a8e1175bSopenharmony_ci    }
388a8e1175bSopenharmony_ci
389a8e1175bSopenharmony_ci    p -= sizeof(memory_header);
390a8e1175bSopenharmony_ci    hdr = (memory_header *) p;
391a8e1175bSopenharmony_ci
392a8e1175bSopenharmony_ci    if (verify_header(hdr) != 0) {
393a8e1175bSopenharmony_ci        mbedtls_exit(1);
394a8e1175bSopenharmony_ci    }
395a8e1175bSopenharmony_ci
396a8e1175bSopenharmony_ci    if (hdr->alloc != 1) {
397a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
398a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "FATAL: mbedtls_free() on unallocated "
399a8e1175bSopenharmony_ci                                "data\n");
400a8e1175bSopenharmony_ci#endif
401a8e1175bSopenharmony_ci        mbedtls_exit(1);
402a8e1175bSopenharmony_ci    }
403a8e1175bSopenharmony_ci
404a8e1175bSopenharmony_ci    hdr->alloc = 0;
405a8e1175bSopenharmony_ci
406a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
407a8e1175bSopenharmony_ci    heap.free_count++;
408a8e1175bSopenharmony_ci    heap.total_used -= hdr->size;
409a8e1175bSopenharmony_ci#endif
410a8e1175bSopenharmony_ci
411a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_BACKTRACE)
412a8e1175bSopenharmony_ci    free(hdr->trace);
413a8e1175bSopenharmony_ci    hdr->trace = NULL;
414a8e1175bSopenharmony_ci    hdr->trace_count = 0;
415a8e1175bSopenharmony_ci#endif
416a8e1175bSopenharmony_ci
417a8e1175bSopenharmony_ci    // Regroup with block before
418a8e1175bSopenharmony_ci    //
419a8e1175bSopenharmony_ci    if (hdr->prev != NULL && hdr->prev->alloc == 0) {
420a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
421a8e1175bSopenharmony_ci        heap.header_count--;
422a8e1175bSopenharmony_ci#endif
423a8e1175bSopenharmony_ci        hdr->prev->size += sizeof(memory_header) + hdr->size;
424a8e1175bSopenharmony_ci        hdr->prev->next = hdr->next;
425a8e1175bSopenharmony_ci        old = hdr;
426a8e1175bSopenharmony_ci        hdr = hdr->prev;
427a8e1175bSopenharmony_ci
428a8e1175bSopenharmony_ci        if (hdr->next != NULL) {
429a8e1175bSopenharmony_ci            hdr->next->prev = hdr;
430a8e1175bSopenharmony_ci        }
431a8e1175bSopenharmony_ci
432a8e1175bSopenharmony_ci        memset(old, 0, sizeof(memory_header));
433a8e1175bSopenharmony_ci    }
434a8e1175bSopenharmony_ci
435a8e1175bSopenharmony_ci    // Regroup with block after
436a8e1175bSopenharmony_ci    //
437a8e1175bSopenharmony_ci    if (hdr->next != NULL && hdr->next->alloc == 0) {
438a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
439a8e1175bSopenharmony_ci        heap.header_count--;
440a8e1175bSopenharmony_ci#endif
441a8e1175bSopenharmony_ci        hdr->size += sizeof(memory_header) + hdr->next->size;
442a8e1175bSopenharmony_ci        old = hdr->next;
443a8e1175bSopenharmony_ci        hdr->next = hdr->next->next;
444a8e1175bSopenharmony_ci
445a8e1175bSopenharmony_ci        if (hdr->prev_free != NULL || hdr->next_free != NULL) {
446a8e1175bSopenharmony_ci            if (hdr->prev_free != NULL) {
447a8e1175bSopenharmony_ci                hdr->prev_free->next_free = hdr->next_free;
448a8e1175bSopenharmony_ci            } else {
449a8e1175bSopenharmony_ci                heap.first_free = hdr->next_free;
450a8e1175bSopenharmony_ci            }
451a8e1175bSopenharmony_ci
452a8e1175bSopenharmony_ci            if (hdr->next_free != NULL) {
453a8e1175bSopenharmony_ci                hdr->next_free->prev_free = hdr->prev_free;
454a8e1175bSopenharmony_ci            }
455a8e1175bSopenharmony_ci        }
456a8e1175bSopenharmony_ci
457a8e1175bSopenharmony_ci        hdr->prev_free = old->prev_free;
458a8e1175bSopenharmony_ci        hdr->next_free = old->next_free;
459a8e1175bSopenharmony_ci
460a8e1175bSopenharmony_ci        if (hdr->prev_free != NULL) {
461a8e1175bSopenharmony_ci            hdr->prev_free->next_free = hdr;
462a8e1175bSopenharmony_ci        } else {
463a8e1175bSopenharmony_ci            heap.first_free = hdr;
464a8e1175bSopenharmony_ci        }
465a8e1175bSopenharmony_ci
466a8e1175bSopenharmony_ci        if (hdr->next_free != NULL) {
467a8e1175bSopenharmony_ci            hdr->next_free->prev_free = hdr;
468a8e1175bSopenharmony_ci        }
469a8e1175bSopenharmony_ci
470a8e1175bSopenharmony_ci        if (hdr->next != NULL) {
471a8e1175bSopenharmony_ci            hdr->next->prev = hdr;
472a8e1175bSopenharmony_ci        }
473a8e1175bSopenharmony_ci
474a8e1175bSopenharmony_ci        memset(old, 0, sizeof(memory_header));
475a8e1175bSopenharmony_ci    }
476a8e1175bSopenharmony_ci
477a8e1175bSopenharmony_ci    // Prepend to free_list if we have not merged
478a8e1175bSopenharmony_ci    // (Does not have to stay in same order as prev / next list)
479a8e1175bSopenharmony_ci    //
480a8e1175bSopenharmony_ci    if (old == NULL) {
481a8e1175bSopenharmony_ci        hdr->next_free = heap.first_free;
482a8e1175bSopenharmony_ci        if (heap.first_free != NULL) {
483a8e1175bSopenharmony_ci            heap.first_free->prev_free = hdr;
484a8e1175bSopenharmony_ci        }
485a8e1175bSopenharmony_ci        heap.first_free = hdr;
486a8e1175bSopenharmony_ci    }
487a8e1175bSopenharmony_ci
488a8e1175bSopenharmony_ci    if ((heap.verify & MBEDTLS_MEMORY_VERIFY_FREE) && verify_chain() != 0) {
489a8e1175bSopenharmony_ci        mbedtls_exit(1);
490a8e1175bSopenharmony_ci    }
491a8e1175bSopenharmony_ci}
492a8e1175bSopenharmony_ci
493a8e1175bSopenharmony_civoid mbedtls_memory_buffer_set_verify(int verify)
494a8e1175bSopenharmony_ci{
495a8e1175bSopenharmony_ci    heap.verify = verify;
496a8e1175bSopenharmony_ci}
497a8e1175bSopenharmony_ci
498a8e1175bSopenharmony_ciint mbedtls_memory_buffer_alloc_verify(void)
499a8e1175bSopenharmony_ci{
500a8e1175bSopenharmony_ci    return verify_chain();
501a8e1175bSopenharmony_ci}
502a8e1175bSopenharmony_ci
503a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
504a8e1175bSopenharmony_civoid mbedtls_memory_buffer_alloc_status(void)
505a8e1175bSopenharmony_ci{
506a8e1175bSopenharmony_ci    mbedtls_fprintf(stderr,
507a8e1175bSopenharmony_ci                    "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
508a8e1175bSopenharmony_ci                    "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
509a8e1175bSopenharmony_ci                    heap.header_count, heap.total_used,
510a8e1175bSopenharmony_ci                    heap.maximum_header_count, heap.maximum_used,
511a8e1175bSopenharmony_ci                    heap.maximum_header_count * sizeof(memory_header)
512a8e1175bSopenharmony_ci                    + heap.maximum_used,
513a8e1175bSopenharmony_ci                    heap.alloc_count, heap.free_count);
514a8e1175bSopenharmony_ci
515a8e1175bSopenharmony_ci    if (heap.first->next == NULL) {
516a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "All memory de-allocated in stack buffer\n");
517a8e1175bSopenharmony_ci    } else {
518a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "Memory currently allocated:\n");
519a8e1175bSopenharmony_ci        debug_chain();
520a8e1175bSopenharmony_ci    }
521a8e1175bSopenharmony_ci}
522a8e1175bSopenharmony_ci
523a8e1175bSopenharmony_civoid mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count)
524a8e1175bSopenharmony_ci{
525a8e1175bSopenharmony_ci    *alloc_count = heap.alloc_count;
526a8e1175bSopenharmony_ci    *free_count = heap.free_count;
527a8e1175bSopenharmony_ci}
528a8e1175bSopenharmony_ci
529a8e1175bSopenharmony_civoid mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks)
530a8e1175bSopenharmony_ci{
531a8e1175bSopenharmony_ci    *max_used   = heap.maximum_used;
532a8e1175bSopenharmony_ci    *max_blocks = heap.maximum_header_count;
533a8e1175bSopenharmony_ci}
534a8e1175bSopenharmony_ci
535a8e1175bSopenharmony_civoid mbedtls_memory_buffer_alloc_max_reset(void)
536a8e1175bSopenharmony_ci{
537a8e1175bSopenharmony_ci    heap.maximum_used = 0;
538a8e1175bSopenharmony_ci    heap.maximum_header_count = 0;
539a8e1175bSopenharmony_ci}
540a8e1175bSopenharmony_ci
541a8e1175bSopenharmony_civoid mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks)
542a8e1175bSopenharmony_ci{
543a8e1175bSopenharmony_ci    *cur_used   = heap.total_used;
544a8e1175bSopenharmony_ci    *cur_blocks = heap.header_count;
545a8e1175bSopenharmony_ci}
546a8e1175bSopenharmony_ci#endif /* MBEDTLS_MEMORY_DEBUG */
547a8e1175bSopenharmony_ci
548a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
549a8e1175bSopenharmony_cistatic void *buffer_alloc_calloc_mutexed(size_t n, size_t size)
550a8e1175bSopenharmony_ci{
551a8e1175bSopenharmony_ci    void *buf;
552a8e1175bSopenharmony_ci    if (mbedtls_mutex_lock(&heap.mutex) != 0) {
553a8e1175bSopenharmony_ci        return NULL;
554a8e1175bSopenharmony_ci    }
555a8e1175bSopenharmony_ci    buf = buffer_alloc_calloc(n, size);
556a8e1175bSopenharmony_ci    if (mbedtls_mutex_unlock(&heap.mutex)) {
557a8e1175bSopenharmony_ci        return NULL;
558a8e1175bSopenharmony_ci    }
559a8e1175bSopenharmony_ci    return buf;
560a8e1175bSopenharmony_ci}
561a8e1175bSopenharmony_ci
562a8e1175bSopenharmony_cistatic void buffer_alloc_free_mutexed(void *ptr)
563a8e1175bSopenharmony_ci{
564a8e1175bSopenharmony_ci    /* We have no good option here, but corrupting the heap seems
565a8e1175bSopenharmony_ci     * worse than losing memory. */
566a8e1175bSopenharmony_ci    if (mbedtls_mutex_lock(&heap.mutex)) {
567a8e1175bSopenharmony_ci        return;
568a8e1175bSopenharmony_ci    }
569a8e1175bSopenharmony_ci    buffer_alloc_free(ptr);
570a8e1175bSopenharmony_ci    (void) mbedtls_mutex_unlock(&heap.mutex);
571a8e1175bSopenharmony_ci}
572a8e1175bSopenharmony_ci#endif /* MBEDTLS_THREADING_C */
573a8e1175bSopenharmony_ci
574a8e1175bSopenharmony_civoid mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len)
575a8e1175bSopenharmony_ci{
576a8e1175bSopenharmony_ci    memset(&heap, 0, sizeof(buffer_alloc_ctx));
577a8e1175bSopenharmony_ci
578a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
579a8e1175bSopenharmony_ci    mbedtls_mutex_init(&heap.mutex);
580a8e1175bSopenharmony_ci    mbedtls_platform_set_calloc_free(buffer_alloc_calloc_mutexed,
581a8e1175bSopenharmony_ci                                     buffer_alloc_free_mutexed);
582a8e1175bSopenharmony_ci#else
583a8e1175bSopenharmony_ci    mbedtls_platform_set_calloc_free(buffer_alloc_calloc, buffer_alloc_free);
584a8e1175bSopenharmony_ci#endif
585a8e1175bSopenharmony_ci
586a8e1175bSopenharmony_ci    if (len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
587a8e1175bSopenharmony_ci        return;
588a8e1175bSopenharmony_ci    } else if ((size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
589a8e1175bSopenharmony_ci        /* Adjust len first since buf is used in the computation */
590a8e1175bSopenharmony_ci        len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
591a8e1175bSopenharmony_ci               - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
592a8e1175bSopenharmony_ci        buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
593a8e1175bSopenharmony_ci               - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
594a8e1175bSopenharmony_ci    }
595a8e1175bSopenharmony_ci
596a8e1175bSopenharmony_ci    memset(buf, 0, len);
597a8e1175bSopenharmony_ci
598a8e1175bSopenharmony_ci    heap.buf = buf;
599a8e1175bSopenharmony_ci    heap.len = len;
600a8e1175bSopenharmony_ci
601a8e1175bSopenharmony_ci    heap.first = (memory_header *) buf;
602a8e1175bSopenharmony_ci    heap.first->size = len - sizeof(memory_header);
603a8e1175bSopenharmony_ci    heap.first->magic1 = MAGIC1;
604a8e1175bSopenharmony_ci    heap.first->magic2 = MAGIC2;
605a8e1175bSopenharmony_ci    heap.first_free = heap.first;
606a8e1175bSopenharmony_ci}
607a8e1175bSopenharmony_ci
608a8e1175bSopenharmony_civoid mbedtls_memory_buffer_alloc_free(void)
609a8e1175bSopenharmony_ci{
610a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
611a8e1175bSopenharmony_ci    mbedtls_mutex_free(&heap.mutex);
612a8e1175bSopenharmony_ci#endif
613a8e1175bSopenharmony_ci    mbedtls_platform_zeroize(&heap, sizeof(buffer_alloc_ctx));
614a8e1175bSopenharmony_ci}
615a8e1175bSopenharmony_ci
616a8e1175bSopenharmony_ci#if defined(MBEDTLS_SELF_TEST)
617a8e1175bSopenharmony_cistatic int check_pointer(void *p)
618a8e1175bSopenharmony_ci{
619a8e1175bSopenharmony_ci    if (p == NULL) {
620a8e1175bSopenharmony_ci        return -1;
621a8e1175bSopenharmony_ci    }
622a8e1175bSopenharmony_ci
623a8e1175bSopenharmony_ci    if ((size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0) {
624a8e1175bSopenharmony_ci        return -1;
625a8e1175bSopenharmony_ci    }
626a8e1175bSopenharmony_ci
627a8e1175bSopenharmony_ci    return 0;
628a8e1175bSopenharmony_ci}
629a8e1175bSopenharmony_ci
630a8e1175bSopenharmony_cistatic int check_all_free(void)
631a8e1175bSopenharmony_ci{
632a8e1175bSopenharmony_ci    if (
633a8e1175bSopenharmony_ci#if defined(MBEDTLS_MEMORY_DEBUG)
634a8e1175bSopenharmony_ci        heap.total_used != 0 ||
635a8e1175bSopenharmony_ci#endif
636a8e1175bSopenharmony_ci        heap.first != heap.first_free ||
637a8e1175bSopenharmony_ci        (void *) heap.first != (void *) heap.buf) {
638a8e1175bSopenharmony_ci        return -1;
639a8e1175bSopenharmony_ci    }
640a8e1175bSopenharmony_ci
641a8e1175bSopenharmony_ci    return 0;
642a8e1175bSopenharmony_ci}
643a8e1175bSopenharmony_ci
644a8e1175bSopenharmony_ci#define TEST_ASSERT(condition)            \
645a8e1175bSopenharmony_ci    if (!(condition))                     \
646a8e1175bSopenharmony_ci    {                                       \
647a8e1175bSopenharmony_ci        if (verbose != 0)                  \
648a8e1175bSopenharmony_ci        mbedtls_printf("failed\n");  \
649a8e1175bSopenharmony_ci                                            \
650a8e1175bSopenharmony_ci        ret = 1;                            \
651a8e1175bSopenharmony_ci        goto cleanup;                       \
652a8e1175bSopenharmony_ci    }
653a8e1175bSopenharmony_ci
654a8e1175bSopenharmony_ciint mbedtls_memory_buffer_alloc_self_test(int verbose)
655a8e1175bSopenharmony_ci{
656a8e1175bSopenharmony_ci    unsigned char buf[1024];
657a8e1175bSopenharmony_ci    unsigned char *p, *q, *r, *end;
658a8e1175bSopenharmony_ci    int ret = 0;
659a8e1175bSopenharmony_ci
660a8e1175bSopenharmony_ci    if (verbose != 0) {
661a8e1175bSopenharmony_ci        mbedtls_printf("  MBA test #1 (basic alloc-free cycle): ");
662a8e1175bSopenharmony_ci    }
663a8e1175bSopenharmony_ci
664a8e1175bSopenharmony_ci    mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
665a8e1175bSopenharmony_ci
666a8e1175bSopenharmony_ci    p = mbedtls_calloc(1, 1);
667a8e1175bSopenharmony_ci    q = mbedtls_calloc(1, 128);
668a8e1175bSopenharmony_ci    r = mbedtls_calloc(1, 16);
669a8e1175bSopenharmony_ci
670a8e1175bSopenharmony_ci    TEST_ASSERT(check_pointer(p) == 0 &&
671a8e1175bSopenharmony_ci                check_pointer(q) == 0 &&
672a8e1175bSopenharmony_ci                check_pointer(r) == 0);
673a8e1175bSopenharmony_ci
674a8e1175bSopenharmony_ci    mbedtls_free(r);
675a8e1175bSopenharmony_ci    mbedtls_free(q);
676a8e1175bSopenharmony_ci    mbedtls_free(p);
677a8e1175bSopenharmony_ci
678a8e1175bSopenharmony_ci    TEST_ASSERT(check_all_free() == 0);
679a8e1175bSopenharmony_ci
680a8e1175bSopenharmony_ci    /* Memorize end to compare with the next test */
681a8e1175bSopenharmony_ci    end = heap.buf + heap.len;
682a8e1175bSopenharmony_ci
683a8e1175bSopenharmony_ci    mbedtls_memory_buffer_alloc_free();
684a8e1175bSopenharmony_ci
685a8e1175bSopenharmony_ci    if (verbose != 0) {
686a8e1175bSopenharmony_ci        mbedtls_printf("passed\n");
687a8e1175bSopenharmony_ci    }
688a8e1175bSopenharmony_ci
689a8e1175bSopenharmony_ci    if (verbose != 0) {
690a8e1175bSopenharmony_ci        mbedtls_printf("  MBA test #2 (buf not aligned): ");
691a8e1175bSopenharmony_ci    }
692a8e1175bSopenharmony_ci
693a8e1175bSopenharmony_ci    mbedtls_memory_buffer_alloc_init(buf + 1, sizeof(buf) - 1);
694a8e1175bSopenharmony_ci
695a8e1175bSopenharmony_ci    TEST_ASSERT(heap.buf + heap.len == end);
696a8e1175bSopenharmony_ci
697a8e1175bSopenharmony_ci    p = mbedtls_calloc(1, 1);
698a8e1175bSopenharmony_ci    q = mbedtls_calloc(1, 128);
699a8e1175bSopenharmony_ci    r = mbedtls_calloc(1, 16);
700a8e1175bSopenharmony_ci
701a8e1175bSopenharmony_ci    TEST_ASSERT(check_pointer(p) == 0 &&
702a8e1175bSopenharmony_ci                check_pointer(q) == 0 &&
703a8e1175bSopenharmony_ci                check_pointer(r) == 0);
704a8e1175bSopenharmony_ci
705a8e1175bSopenharmony_ci    mbedtls_free(r);
706a8e1175bSopenharmony_ci    mbedtls_free(q);
707a8e1175bSopenharmony_ci    mbedtls_free(p);
708a8e1175bSopenharmony_ci
709a8e1175bSopenharmony_ci    TEST_ASSERT(check_all_free() == 0);
710a8e1175bSopenharmony_ci
711a8e1175bSopenharmony_ci    mbedtls_memory_buffer_alloc_free();
712a8e1175bSopenharmony_ci
713a8e1175bSopenharmony_ci    if (verbose != 0) {
714a8e1175bSopenharmony_ci        mbedtls_printf("passed\n");
715a8e1175bSopenharmony_ci    }
716a8e1175bSopenharmony_ci
717a8e1175bSopenharmony_ci    if (verbose != 0) {
718a8e1175bSopenharmony_ci        mbedtls_printf("  MBA test #3 (full): ");
719a8e1175bSopenharmony_ci    }
720a8e1175bSopenharmony_ci
721a8e1175bSopenharmony_ci    mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
722a8e1175bSopenharmony_ci
723a8e1175bSopenharmony_ci    p = mbedtls_calloc(1, sizeof(buf) - sizeof(memory_header));
724a8e1175bSopenharmony_ci
725a8e1175bSopenharmony_ci    TEST_ASSERT(check_pointer(p) == 0);
726a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
727a8e1175bSopenharmony_ci
728a8e1175bSopenharmony_ci    mbedtls_free(p);
729a8e1175bSopenharmony_ci
730a8e1175bSopenharmony_ci    p = mbedtls_calloc(1, sizeof(buf) - 2 * sizeof(memory_header) - 16);
731a8e1175bSopenharmony_ci    q = mbedtls_calloc(1, 16);
732a8e1175bSopenharmony_ci
733a8e1175bSopenharmony_ci    TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0);
734a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
735a8e1175bSopenharmony_ci
736a8e1175bSopenharmony_ci    mbedtls_free(q);
737a8e1175bSopenharmony_ci
738a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_calloc(1, 17) == NULL);
739a8e1175bSopenharmony_ci
740a8e1175bSopenharmony_ci    mbedtls_free(p);
741a8e1175bSopenharmony_ci
742a8e1175bSopenharmony_ci    TEST_ASSERT(check_all_free() == 0);
743a8e1175bSopenharmony_ci
744a8e1175bSopenharmony_ci    mbedtls_memory_buffer_alloc_free();
745a8e1175bSopenharmony_ci
746a8e1175bSopenharmony_ci    if (verbose != 0) {
747a8e1175bSopenharmony_ci        mbedtls_printf("passed\n");
748a8e1175bSopenharmony_ci    }
749a8e1175bSopenharmony_ci
750a8e1175bSopenharmony_cicleanup:
751a8e1175bSopenharmony_ci    mbedtls_memory_buffer_alloc_free();
752a8e1175bSopenharmony_ci
753a8e1175bSopenharmony_ci    return ret;
754a8e1175bSopenharmony_ci}
755a8e1175bSopenharmony_ci#endif /* MBEDTLS_SELF_TEST */
756a8e1175bSopenharmony_ci
757a8e1175bSopenharmony_ci#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
758