GCC Code Coverage Report


Directory: src/
File: src/mpq-block.c
Date: 2026-10-06 13:47:41
Exec Total Coverage
Lines: 40 40 100.0%
Functions: 4 4 100.0%
Branches: 40 48 83.3%

Line Branch Exec Source
1 /*
2 * mpq-block.c -- MPQ block-table wire-format encoding and decoding.
3 *
4 * Copyright (c) 2026-2026 Maik Broemme <mbroemme@libmpq.org>
5 *
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
10 *
11 * This file is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this file; if not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "mpq-block.h"
21 #include "mpq-endian.h"
22 #include <libmpq/mpq.h>
23
24 /* Decode base entries without interpreting flags or file positions. */
25 int32_t
26 1626 libmpq__block_table_decode(
27 const uint8_t *input, size_t input_size, mpq_block_s *entries, size_t entry_count
28 )
29 {
30 size_t i;
31
32
2/2
✓ Branch 0 taken 1625 times.
✓ Branch 1 taken 1 times.
1626 if (entry_count > SIZE_MAX / LIBMPQ_BLOCK_ENTRY_WIRE_SIZE ||
33
4/4
✓ Branch 0 taken 1624 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1622 times.
✓ Branch 3 taken 2 times.
1625 input_size < entry_count * LIBMPQ_BLOCK_ENTRY_WIRE_SIZE ||
34
2/4
✓ Branch 0 taken 1622 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1622 times.
1622 (entry_count != 0 && (input == NULL || entries == NULL)))
35 2 return LIBMPQ_ERROR_SIZE;
36
37
2/2
✓ Branch 0 taken 116776 times.
✓ Branch 1 taken 1624 times.
118400 for (i = 0; i < entry_count; i++) {
38 116776 const uint8_t *wire = input + i * LIBMPQ_BLOCK_ENTRY_WIRE_SIZE;
39
40 116776 entries[i].offset = libmpq__load_le32(wire);
41 116776 entries[i].packed_size = libmpq__load_le32(wire + 4);
42 116776 entries[i].unpacked_size = libmpq__load_le32(wire + 8);
43 116776 entries[i].flags = libmpq__load_le32(wire + 12);
44 }
45 1624 return 0;
46 }
47
48 /* Encode base entries into caller-owned bytes before table encryption. */
49 int32_t
50 743 libmpq__block_table_encode(
51 const mpq_block_s *entries, size_t entry_count, uint8_t *output, size_t output_size
52 )
53 {
54 size_t i;
55
56
2/2
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 1 times.
743 if (entry_count > SIZE_MAX / LIBMPQ_BLOCK_ENTRY_WIRE_SIZE ||
57
4/4
✓ Branch 0 taken 741 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 740 times.
✓ Branch 3 taken 1 times.
742 output_size < entry_count * LIBMPQ_BLOCK_ENTRY_WIRE_SIZE ||
58
2/4
✓ Branch 0 taken 740 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 740 times.
740 (entry_count != 0 && (entries == NULL || output == NULL)))
59 2 return LIBMPQ_ERROR_SIZE;
60
61
2/2
✓ Branch 0 taken 39914 times.
✓ Branch 1 taken 741 times.
40655 for (i = 0; i < entry_count; i++) {
62 39914 uint8_t *wire = output + i * LIBMPQ_BLOCK_ENTRY_WIRE_SIZE;
63
64 39914 libmpq__store_le32(wire, entries[i].offset);
65 39914 libmpq__store_le32(wire + 4, entries[i].packed_size);
66 39914 libmpq__store_le32(wire + 8, entries[i].unpacked_size);
67 39914 libmpq__store_le32(wire + 12, entries[i].flags);
68 }
69 741 return 0;
70 }
71
72 /* Decode the optional v2 high-offset words without changing their values. */
73 int32_t
74 497 libmpq__block_ex_table_decode(
75 const uint8_t *input, size_t input_size, mpq_block_ex_s *entries, size_t entry_count
76 )
77 {
78 size_t i;
79
80
2/2
✓ Branch 0 taken 496 times.
✓ Branch 1 taken 1 times.
497 if (entry_count > SIZE_MAX / LIBMPQ_BLOCK_EX_ENTRY_WIRE_SIZE ||
81
4/4
✓ Branch 0 taken 495 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 494 times.
✓ Branch 3 taken 1 times.
496 input_size < entry_count * LIBMPQ_BLOCK_EX_ENTRY_WIRE_SIZE ||
82
2/4
✓ Branch 0 taken 494 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 494 times.
494 (entry_count != 0 && (input == NULL || entries == NULL)))
83 2 return LIBMPQ_ERROR_SIZE;
84
85
2/2
✓ Branch 0 taken 54623 times.
✓ Branch 1 taken 495 times.
55118 for (i = 0; i < entry_count; i++)
86 54623 entries[i].offset_high = libmpq__load_le16(input + i * LIBMPQ_BLOCK_EX_ENTRY_WIRE_SIZE);
87 495 return 0;
88 }
89
90 /* Encode the optional v2 high-offset words in little-endian order. */
91 int32_t
92 851 libmpq__block_ex_table_encode(
93 const mpq_block_ex_s *entries, size_t entry_count, uint8_t *output, size_t output_size
94 )
95 {
96 size_t i;
97
98
2/2
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 1 times.
851 if (entry_count > SIZE_MAX / LIBMPQ_BLOCK_EX_ENTRY_WIRE_SIZE ||
99
4/4
✓ Branch 0 taken 849 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 848 times.
✓ Branch 3 taken 1 times.
850 output_size < entry_count * LIBMPQ_BLOCK_EX_ENTRY_WIRE_SIZE ||
100
2/4
✓ Branch 0 taken 848 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 848 times.
848 (entry_count != 0 && (entries == NULL || output == NULL)))
101 2 return LIBMPQ_ERROR_SIZE;
102
103
2/2
✓ Branch 0 taken 12864 times.
✓ Branch 1 taken 849 times.
13713 for (i = 0; i < entry_count; i++)
104 12864 libmpq__store_le16(output + i * LIBMPQ_BLOCK_EX_ENTRY_WIRE_SIZE, entries[i].offset_high);
105 849 return 0;
106 }
107