Code Coverage Report for src/util/memory.c


Hit Total Coverage
Lines: 43 43 100.0%
Branches: 252 252 100.0%

1 /*
2 * libnogg: a decoder library for Ogg Vorbis streams
3 * Copyright (c) 2014-2023 Andrew Church <achurch@achurch.org>
4 *
5 * This software may be copied and redistributed under certain conditions;
6 * see the file "COPYING" in the source code distribution for details.
7 * NO WARRANTY is provided with this software.
8 */
9
10 #include "include/nogg.h"
11 #include "src/common.h"
12 #include "src/util/memory.h"
13
14 #include <stdlib.h>
15
16 /*************************************************************************/
17 /************************** Interface routines ***************************/
18 /*************************************************************************/
19
20 void *mem_alloc(vorbis_t *handle, int32_t size, int32_t align)
21 {
22 ASSERT(size >= 0);
23 ASSERT(align >= 0);
24 ASSERT((align & (align - 1)) == 0);
25
26 (18/18) if (handle->callbacks.malloc) {
27 return (*handle->callbacks.malloc)(handle->callback_data, size, align);
28 } else {
29 int32_t size_to_alloc = size + sizeof(void *);
30 (18/18) if (align > (int)sizeof(void *)) {
31 size_to_alloc += align - sizeof(void *);
32 }
33 void *base = malloc(size_to_alloc);
34 (18/18) if (UNLIKELY(!base)) {
35 return NULL;
36 }
37 ASSERT((uintptr_t)base % sizeof(void *) == 0);
38 void *ptr = (void *)((uintptr_t)base + sizeof(void *));
39 (36/36) if (align != 0 && (uintptr_t)ptr % align != 0) {
40 ptr = (void *)((uintptr_t)ptr + (align - ((uintptr_t)ptr % align)));
41 }
42 ((void **)ptr)[-1] = base;
43 return ptr;
44 }
45 }
46
47 /*-----------------------------------------------------------------------*/
48
49 void mem_free(vorbis_t *handle, void *ptr)
50 {
51 (18/18) if (handle->callbacks.free) {
52 (*handle->callbacks.free)(handle->callback_data, ptr);
53 } else {
54 (18/18) if (ptr) {
55 free(((void **)ptr)[-1]);
56 }
57 }
58 }
59
60 /*-----------------------------------------------------------------------*/
61
62 void *alloc_channel_array(vorbis_t *handle, int channels, int32_t size,
63 int32_t align)
64 {
65 ASSERT(size >= 0);
66 ASSERT(align >= 0);
67 ASSERT((align & (align - 1)) == 0);
68
69 int32_t array_size = sizeof(void *) * channels;
70 (36/36) if (align != 0 && array_size % align != 0) {
71 array_size += align - (array_size % align);
72 }
73 int32_t subarray_size = size;
74 (36/36) if (align != 0 && subarray_size % align != 0) {
75 subarray_size += align - (subarray_size % align);
76 }
77
78 const int64_t alloc_size = (int64_t)channels * subarray_size + array_size;
79 (18/18) if (alloc_size > 0x7FFFFFFF) {
80 return NULL; // Avoid integer overflow in mem_alloc() call.
81 }
82
83 char **array = mem_alloc(handle, (int32_t)alloc_size, align);
84 (18/18) if (array) {
85 char *subarray_base = (char *)array + array_size;
86 (18/18) for (int channel = 0; channel < channels; channel++) {
87 array[channel] = subarray_base + (channel * subarray_size);
88 }
89 }
90 return array;
91 }
92
93 /*************************************************************************/
94 /*************************************************************************/