Coverage Report

Created: 2026-07-25 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/src/utils.c
Line
Count
Source
1
// Copyright 2019 Joe Drago. All rights reserved.
2
// SPDX-License-Identifier: BSD-2-Clause
3
4
#include "avif/internal.h"
5
6
#include <assert.h>
7
#include <math.h>
8
#include <stdint.h>
9
#include <string.h>
10
11
float avifRoundf(float v)
12
1.46M
{
13
1.46M
    return floorf(v + 0.5f);
14
1.46M
}
15
16
// Thanks, Rob Pike! https://commandcenter.blogspot.nl/2012/04/byte-order-fallacy.html
17
18
uint16_t avifHTONS(uint16_t s)
19
0
{
20
0
    uint16_t result = 0;
21
0
    uint8_t * data = (uint8_t *)&result;
22
0
    data[0] = (s >> 8) & 0xff;
23
0
    data[1] = (s >> 0) & 0xff;
24
0
    return result;
25
0
}
26
27
uint16_t avifNTOHS(uint16_t s)
28
137k
{
29
137k
    const uint8_t * data = (const uint8_t *)&s;
30
137k
    return (uint16_t)((data[1] << 0) | (data[0] << 8));
31
137k
}
32
33
uint16_t avifCTOHS(uint16_t s)
34
0
{
35
0
    const uint8_t * data = (const uint8_t *)&s;
36
0
    return (uint16_t)((data[0] << 0) | (data[1] << 8));
37
0
}
38
39
uint32_t avifHTONL(uint32_t l)
40
0
{
41
0
    uint32_t result = 0;
42
0
    uint8_t * data = (uint8_t *)&result;
43
0
    data[0] = (l >> 24) & 0xff;
44
0
    data[1] = (l >> 16) & 0xff;
45
0
    data[2] = (l >> 8) & 0xff;
46
0
    data[3] = (l >> 0) & 0xff;
47
0
    return result;
48
0
}
49
50
uint32_t avifNTOHL(uint32_t l)
51
350k
{
52
350k
    const uint8_t * data = (const uint8_t *)&l;
53
350k
    return ((uint32_t)data[3] << 0) | ((uint32_t)data[2] << 8) | ((uint32_t)data[1] << 16) | ((uint32_t)data[0] << 24);
54
350k
}
55
56
uint32_t avifCTOHL(uint32_t l)
57
0
{
58
0
    const uint8_t * data = (const uint8_t *)&l;
59
0
    return ((uint32_t)data[0] << 0) | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
60
0
}
61
62
uint64_t avifHTON64(uint64_t l)
63
0
{
64
0
    uint64_t result = 0;
65
0
    uint8_t * data = (uint8_t *)&result;
66
0
    data[0] = (l >> 56) & 0xff;
67
0
    data[1] = (l >> 48) & 0xff;
68
0
    data[2] = (l >> 40) & 0xff;
69
0
    data[3] = (l >> 32) & 0xff;
70
0
    data[4] = (l >> 24) & 0xff;
71
0
    data[5] = (l >> 16) & 0xff;
72
0
    data[6] = (l >> 8) & 0xff;
73
0
    data[7] = (l >> 0) & 0xff;
74
0
    return result;
75
0
}
76
77
uint64_t avifNTOH64(uint64_t l)
78
1.82k
{
79
1.82k
    const uint8_t * data = (const uint8_t *)&l;
80
1.82k
    return ((uint64_t)data[7] << 0) | ((uint64_t)data[6] << 8) | ((uint64_t)data[5] << 16) | ((uint64_t)data[4] << 24) |
81
1.82k
           ((uint64_t)data[3] << 32) | ((uint64_t)data[2] << 40) | ((uint64_t)data[1] << 48) | ((uint64_t)data[0] << 56);
82
1.82k
}
83
84
AVIF_ARRAY_DECLARE(avifArrayInternal, uint8_t, ptr);
85
86
// On error, this function must set arr->ptr to NULL and both arr->count and arr->capacity to 0.
87
avifBool avifArrayCreate(void * arrayStruct, uint32_t elementSize, uint32_t initialCapacity)
88
131k
{
89
131k
    avifArrayInternal * arr = (avifArrayInternal *)arrayStruct;
90
131k
    arr->elementSize = elementSize ? elementSize : 1;
91
131k
    arr->count = 0;
92
131k
    arr->capacity = initialCapacity;
93
131k
    if (arr->capacity > SIZE_MAX / arr->elementSize) {
94
0
        arr->ptr = NULL;
95
0
        arr->capacity = 0;
96
0
        return AVIF_FALSE;
97
0
    }
98
131k
    size_t byteCount = (size_t)arr->elementSize * arr->capacity;
99
131k
    arr->ptr = (uint8_t *)avifAlloc(byteCount);
100
131k
    if (!arr->ptr) {
101
0
        arr->capacity = 0;
102
0
        return AVIF_FALSE;
103
0
    }
104
131k
    memset(arr->ptr, 0, byteCount);
105
131k
    return AVIF_TRUE;
106
131k
}
107
108
void * avifArrayPush(void * arrayStruct)
109
8.95M
{
110
8.95M
    avifArrayInternal * arr = (avifArrayInternal *)arrayStruct;
111
8.95M
    if (arr->count == arr->capacity) {
112
4.60k
        uint8_t * oldPtr = arr->ptr;
113
4.60k
        size_t oldByteCount = (size_t)arr->elementSize * arr->capacity;
114
4.60k
        if (oldByteCount > SIZE_MAX / 2 || arr->capacity > UINT32_MAX / 2) {
115
0
            return NULL;
116
0
        }
117
4.60k
        size_t newByteCount = oldByteCount * 2;
118
4.60k
        uint8_t * newPtr = (uint8_t *)avifAlloc(newByteCount);
119
4.60k
        if (newPtr == NULL) {
120
0
            return NULL;
121
0
        }
122
4.60k
        arr->ptr = newPtr;
123
4.60k
        memset(arr->ptr + oldByteCount, 0, oldByteCount);
124
4.60k
        memcpy(arr->ptr, oldPtr, oldByteCount);
125
4.60k
        arr->capacity *= 2;
126
4.60k
        avifFree(oldPtr);
127
4.60k
    }
128
8.95M
    ++arr->count;
129
8.95M
    return &arr->ptr[(arr->count - 1) * (size_t)arr->elementSize];
130
8.95M
}
131
132
void avifArrayPop(void * arrayStruct)
133
0
{
134
0
    avifArrayInternal * arr = (avifArrayInternal *)arrayStruct;
135
0
    assert(arr->count > 0);
136
0
    --arr->count;
137
0
    memset(&arr->ptr[arr->count * (size_t)arr->elementSize], 0, arr->elementSize);
138
0
}
139
140
void avifArrayDestroy(void * arrayStruct)
141
147k
{
142
147k
    avifArrayInternal * arr = (avifArrayInternal *)arrayStruct;
143
147k
    if (arr->ptr) {
144
131k
        avifFree(arr->ptr);
145
131k
        arr->ptr = NULL;
146
131k
    }
147
147k
    memset(arr, 0, sizeof(avifArrayInternal));
148
147k
}
149
150
// |a| and |b| hold int32_t values. The int64_t type is used so that we can negate INT32_MIN without
151
// overflowing int32_t.
152
static int64_t calcGCD(int64_t a, int64_t b)
153
0
{
154
0
    if (a < 0) {
155
0
        a *= -1;
156
0
    }
157
0
    if (b < 0) {
158
0
        b *= -1;
159
0
    }
160
0
    while (b != 0) {
161
0
        int64_t r = a % b;
162
0
        a = b;
163
0
        b = r;
164
0
    }
165
0
    return a;
166
0
}
167
168
void avifFractionSimplify(avifFraction * f)
169
0
{
170
0
    int64_t gcd = calcGCD(f->n, f->d);
171
0
    if (gcd > 1) {
172
0
        f->n = (int32_t)(f->n / gcd);
173
0
        f->d = (int32_t)(f->d / gcd);
174
0
    }
175
0
}
176
177
static avifBool overflowsInt32(int64_t x)
178
0
{
179
0
    return (x < INT32_MIN) || (x > INT32_MAX);
180
0
}
181
182
avifBool avifFractionCD(avifFraction * a, avifFraction * b)
183
0
{
184
0
    avifFractionSimplify(a);
185
0
    avifFractionSimplify(b);
186
0
    if (a->d != b->d) {
187
0
        const int64_t ad = a->d;
188
0
        const int64_t bd = b->d;
189
0
        const int64_t anNew = a->n * bd;
190
0
        const int64_t adNew = a->d * bd;
191
0
        const int64_t bnNew = b->n * ad;
192
0
        const int64_t bdNew = b->d * ad;
193
0
        if (overflowsInt32(anNew) || overflowsInt32(adNew) || overflowsInt32(bnNew) || overflowsInt32(bdNew)) {
194
0
            return AVIF_FALSE;
195
0
        }
196
0
        a->n = (int32_t)anNew;
197
0
        a->d = (int32_t)adNew;
198
0
        b->n = (int32_t)bnNew;
199
0
        b->d = (int32_t)bdNew;
200
0
    }
201
0
    return AVIF_TRUE;
202
0
}
203
204
avifBool avifFractionAdd(avifFraction a, avifFraction b, avifFraction * result)
205
0
{
206
0
    if (!avifFractionCD(&a, &b)) {
207
0
        return AVIF_FALSE;
208
0
    }
209
210
0
    const int64_t resultN = (int64_t)a.n + b.n;
211
0
    if (overflowsInt32(resultN)) {
212
0
        return AVIF_FALSE;
213
0
    }
214
0
    result->n = (int32_t)resultN;
215
0
    result->d = a.d;
216
217
0
    avifFractionSimplify(result);
218
0
    return AVIF_TRUE;
219
0
}
220
221
avifBool avifFractionSub(avifFraction a, avifFraction b, avifFraction * result)
222
0
{
223
0
    if (!avifFractionCD(&a, &b)) {
224
0
        return AVIF_FALSE;
225
0
    }
226
227
0
    const int64_t resultN = (int64_t)a.n - b.n;
228
0
    if (overflowsInt32(resultN)) {
229
0
        return AVIF_FALSE;
230
0
    }
231
0
    result->n = (int32_t)resultN;
232
0
    result->d = a.d;
233
234
0
    avifFractionSimplify(result);
235
0
    return AVIF_TRUE;
236
0
}
237
238
static avifBool avifDoubleToUnsignedFractionImpl(double v, uint32_t maxNumerator, uint32_t * numerator, uint32_t * denominator)
239
0
{
240
0
    if (isnan(v) || v < 0 || v > maxNumerator) {
241
0
        return AVIF_FALSE;
242
0
    }
243
244
    // Maximum denominator: makes sure that the numerator is <= maxNumerator and the denominator is <= UINT32_MAX.
245
0
    const uint32_t maxD = (v <= 1) ? UINT32_MAX : (uint32_t)floor(maxNumerator / v);
246
247
    // Find the best approximation of v as a fraction using continued fractions, see
248
    // https://en.wikipedia.org/wiki/Continued_fraction
249
0
    *denominator = 1;
250
0
    uint32_t previousD = 0;
251
0
    double currentV = v - floor(v);
252
0
    int iter = 0;
253
    // Set a maximum number of iterations to be safe. Most numbers should
254
    // converge in less than ~20 iterations.
255
    // The golden ratio is the worst case and takes 39 iterations.
256
0
    const int maxIter = 39;
257
0
    while (iter < maxIter) {
258
0
        const double numeratorDouble = (double)(*denominator) * v;
259
0
        assert(numeratorDouble <= maxNumerator);
260
0
        *numerator = (uint32_t)round(numeratorDouble);
261
0
        if (fabs(numeratorDouble - (*numerator)) == 0.0) {
262
0
            return AVIF_TRUE;
263
0
        }
264
0
        currentV = 1.0 / currentV;
265
0
        const double newD = previousD + floor(currentV) * (*denominator);
266
0
        if (newD > (double)maxD) {
267
            // This is the best we can do with a denominator <= max_d.
268
0
            return AVIF_TRUE;
269
0
        }
270
0
        previousD = *denominator;
271
0
        assert(newD <= UINT32_MAX);
272
0
        *denominator = (uint32_t)newD;
273
0
        currentV -= floor(currentV);
274
0
        ++iter;
275
0
    }
276
    // Maximum number of iterations reached, return what we've found.
277
    // For max_iter >= 39 we shouldn't get here. max_iter can be set
278
    // to a lower value to speed up the algorithm if needed.
279
0
    *numerator = (uint32_t)round((double)(*denominator) * v);
280
0
    return AVIF_TRUE;
281
0
}
282
283
avifBool avifDoubleToSignedFraction(double v, avifSignedFraction * fraction)
284
0
{
285
0
    uint32_t positive_numerator;
286
0
    if (!avifDoubleToUnsignedFractionImpl(fabs(v), INT32_MAX, &positive_numerator, &fraction->d)) {
287
0
        return AVIF_FALSE;
288
0
    }
289
0
    fraction->n = (int32_t)positive_numerator;
290
0
    if (v < 0) {
291
0
        fraction->n *= -1;
292
0
    }
293
0
    return AVIF_TRUE;
294
0
}
295
296
avifBool avifDoubleToUnsignedFraction(double v, avifUnsignedFraction * fraction)
297
0
{
298
    return avifDoubleToUnsignedFractionImpl(v, UINT32_MAX, &fraction->n, &fraction->d);
299
0
}