Coverage Report

Created: 2025-12-31 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/fitz/pool.c
Line
Count
Source
1
// Copyright (C) 2004-2025 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
25
#include <string.h>
26
#include <stdio.h>
27
28
typedef struct fz_pool_node
29
{
30
  struct fz_pool_node *next;
31
  char mem[FZ_FLEXIBLE_ARRAY];
32
} fz_pool_node;
33
34
0
#define POOL_SIZE (4<<10) /* default size of pool blocks */
35
0
#define POOL_SELF (1<<10) /* size where allocs are put into their own blocks */
36
37
struct fz_pool
38
{
39
  size_t size;
40
  fz_pool_node *head, *tail;
41
  char *pos, *end;
42
};
43
44
45
fz_pool *fz_new_pool(fz_context *ctx)
46
0
{
47
0
  fz_pool *pool;
48
0
  fz_pool_node *node = NULL;
49
50
0
  pool = fz_malloc_struct(ctx, fz_pool);
51
0
  fz_try(ctx)
52
0
  {
53
0
    node = Memento_label(fz_calloc(ctx, offsetof(fz_pool_node, mem) + POOL_SIZE, 1), "fz_pool_block");
54
0
    pool->head = pool->tail = node;
55
0
    pool->pos = node->mem;
56
0
    pool->end = node->mem + POOL_SIZE;
57
0
  }
58
0
  fz_catch(ctx)
59
0
  {
60
0
    fz_free(ctx, pool);
61
0
    fz_rethrow(ctx);
62
0
  }
63
64
0
  return pool;
65
0
}
66
67
static void *fz_pool_alloc_oversize(fz_context *ctx, fz_pool *pool, size_t size)
68
0
{
69
0
  fz_pool_node *node;
70
71
  /* link in memory at the head of the list */
72
0
  node = Memento_label(fz_calloc(ctx, offsetof(fz_pool_node, mem) + size, 1), "fz_pool_oversize");
73
0
  node->next = pool->head;
74
0
  pool->head = node;
75
0
  pool->size += offsetof(fz_pool_node, mem) + size;
76
77
0
  return node->mem;
78
0
}
79
80
void *fz_pool_alloc(fz_context *ctx, fz_pool *pool, size_t size)
81
0
{
82
0
  char *ptr;
83
84
0
  if (size >= POOL_SELF)
85
0
    return fz_pool_alloc_oversize(ctx, pool, size);
86
87
  /* round size to pointer alignment (we don't expect to use doubles) */
88
0
  size = (size + FZ_POINTER_ALIGN_MOD - 1) & ~(FZ_POINTER_ALIGN_MOD-1);
89
90
0
  if (pool->pos + size > pool->end)
91
0
  {
92
0
    fz_pool_node *node = Memento_label(fz_calloc(ctx, offsetof(fz_pool_node, mem) + POOL_SIZE, 1), "fz_pool_block");
93
0
    pool->tail = pool->tail->next = node;
94
0
    pool->pos = node->mem;
95
0
    pool->end = node->mem + POOL_SIZE;
96
0
    pool->size += offsetof(fz_pool_node, mem) + POOL_SIZE;
97
0
  }
98
0
  ptr = pool->pos;
99
0
  pool->pos += size;
100
0
  return ptr;
101
0
}
102
103
char *fz_pool_strdup(fz_context *ctx, fz_pool *pool, const char *s)
104
0
{
105
0
  size_t n = strlen(s) + 1;
106
0
  char *p = fz_pool_alloc(ctx, pool, n);
107
0
  memcpy(p, s, n);
108
0
  return p;
109
0
}
110
111
size_t fz_pool_size(fz_context *ctx, fz_pool *pool)
112
0
{
113
0
  return pool ? pool->size : 0;
114
0
}
115
116
void fz_drop_pool(fz_context *ctx, fz_pool *pool)
117
0
{
118
0
  fz_pool_node *node;
119
120
0
  if (!pool)
121
0
    return;
122
123
0
  node = pool->head;
124
0
  while (node)
125
0
  {
126
0
    fz_pool_node *next = node->next;
127
0
    fz_free(ctx, node);
128
0
    node = next;
129
0
  }
130
0
  fz_free(ctx, pool);
131
0
}
132
133
typedef struct fz_pool_array_section
134
{
135
  struct fz_pool_array_section *next;
136
  size_t len;
137
  char elements[FZ_FLEXIBLE_ARRAY];
138
} fz_pool_array_section;
139
140
struct fz_pool_array
141
{
142
  fz_pool *pool;
143
  size_t size;
144
  size_t len;
145
  fz_pool_array_section head;
146
};
147
148
fz_pool_array *fz_new_pool_array_imp(fz_context *ctx, fz_pool *pool, size_t size, size_t initial)
149
0
{
150
0
  fz_pool_array *arr;
151
152
0
  if (initial <= 0)
153
0
    initial = 4;
154
155
0
  arr = fz_pool_alloc(ctx, pool, sizeof(fz_pool_array) + size * initial);
156
157
0
  arr->pool = pool;
158
0
  arr->size = size;
159
0
  arr->len = 0;
160
0
  arr->head.len = initial;
161
162
0
  return arr;
163
0
}
164
165
void *fz_pool_array_append(fz_context *ctx, fz_pool_array *arr, size_t *idx)
166
0
{
167
0
  size_t len = arr->len;
168
0
  size_t base = 0;
169
0
  fz_pool_array_section *sec = &arr->head;
170
171
0
  while (base + sec->len < len && sec->next != NULL)
172
0
    base += sec->len, sec = sec->next;
173
174
0
  if (base + sec->len == len)
175
0
  {
176
    /* We need to allocate a new block */
177
0
    size_t newlen = sec->len * 2;
178
0
    sec->next = fz_pool_alloc(ctx, arr->pool, sizeof(fz_pool_array_section) + arr->size * newlen);
179
0
    base = len;
180
0
    sec = sec->next;
181
0
    sec->len = newlen;
182
0
  }
183
184
  /* Now insert */
185
0
  arr->len++;
186
0
  if (idx)
187
0
    *idx = len;
188
189
0
  return (void *)(&sec->elements[0] + arr->size * (len - base));
190
0
}
191
192
void *fz_pool_array_lookup(fz_context *ctx, fz_pool_array *arr, size_t idx)
193
0
{
194
0
  size_t base = 0;
195
0
  fz_pool_array_section *sec = &arr->head;
196
197
0
  if (idx >= arr->len)
198
0
    fz_throw(ctx, FZ_ERROR_ARGUMENT, "array is not that long");
199
200
0
  while (base + sec->len < idx)
201
0
    base += sec->len, sec = sec->next;
202
203
0
  return (void *)(&sec->elements[0] + arr->size * (idx - base));
204
0
}
205
206
size_t fz_pool_array_len(fz_context *ctx, fz_pool_array *arr)
207
0
{
208
0
  return arr->len;
209
0
}