Coverage Report

Created: 2026-04-09 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-sum.c
Line
Count
Source
1
/*
2
 * Copyright 2017 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
0
#define G_LOG_DOMAIN "FuCommon"
8
9
#include "config.h"
10
11
#include "fu-mem-private.h"
12
#include "fu-sum.h"
13
14
/**
15
 * fu_sum8:
16
 * @buf: memory buffer
17
 * @bufsz: size of @buf
18
 *
19
 * Returns the arithmetic sum of all bytes in @buf.
20
 *
21
 * Returns: sum value
22
 *
23
 * Since: 1.8.2
24
 **/
25
guint8
26
fu_sum8(const guint8 *buf, gsize bufsz)
27
2.20M
{
28
2.20M
  guint8 checksum = 0;
29
2.20M
  g_return_val_if_fail(buf != NULL || bufsz == 0, G_MAXUINT8);
30
59.4M
  for (gsize i = 0; i < bufsz; i++)
31
57.2M
    checksum += buf[i];
32
2.20M
  return checksum;
33
2.20M
}
34
35
/**
36
 * fu_sum8_safe:
37
 * @buf: source buffer
38
 * @bufsz: maximum size of @buf, typically `sizeof(buf)`
39
 * @offset: offset in bytes into @buf where sum should start
40
 * @n: number of bytes to sum from @buf
41
 * @value: (out) (nullable): the result
42
 * @error: (nullable): optional return location for an error
43
 *
44
 * Returns the arithmetic sum of all bytes in @buf.
45
 *
46
 * You don't need to use this function in "obviously correct" cases, nor should
47
 * you use it when performance is a concern. Only use it when you're not sure if
48
 * malicious data from a device or firmware could cause memory corruption.
49
 *
50
 * Returns: %TRUE on success, %FALSE otherwise
51
 *
52
 * Since: 2.1.2
53
 **/
54
gboolean
55
fu_sum8_safe(const guint8 *buf, gsize bufsz, gsize offset, gsize n, guint8 *value, GError **error)
56
0
{
57
0
  g_return_val_if_fail(buf != NULL || bufsz == 0, FALSE);
58
0
  g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
59
60
0
  if (!fu_memchk_read(bufsz, offset, n, error))
61
0
    return FALSE;
62
0
  if (value != NULL)
63
0
    *value = fu_sum8(buf + offset, n);
64
0
  return TRUE;
65
0
}
66
67
/**
68
 * fu_sum8_bytes:
69
 * @blob: a #GBytes
70
 *
71
 * Returns the arithmetic sum of all bytes in @blob.
72
 *
73
 * Returns: sum value
74
 *
75
 * Since: 1.8.2
76
 **/
77
guint8
78
fu_sum8_bytes(GBytes *blob)
79
350k
{
80
350k
  g_return_val_if_fail(blob != NULL, G_MAXUINT8);
81
350k
  if (g_bytes_get_size(blob) == 0)
82
346k
    return 0;
83
3.74k
  return fu_sum8(g_bytes_get_data(blob, NULL), g_bytes_get_size(blob));
84
350k
}
85
86
/**
87
 * fu_sum16:
88
 * @buf: memory buffer
89
 * @bufsz: size of @buf
90
 *
91
 * Returns the arithmetic sum of all bytes in @buf, adding them one byte at a time.
92
 *
93
 * Returns: sum value
94
 *
95
 * Since: 1.8.2
96
 **/
97
guint16
98
fu_sum16(const guint8 *buf, gsize bufsz)
99
89
{
100
89
  guint16 checksum = 0;
101
89
  g_return_val_if_fail(buf != NULL || bufsz == 0, G_MAXUINT16);
102
2.18M
  for (gsize i = 0; i < bufsz; i++)
103
2.18M
    checksum += buf[i];
104
89
  return checksum;
105
89
}
106
107
/**
108
 * fu_sum16_safe:
109
 * @buf: source buffer
110
 * @bufsz: maximum size of @buf, typically `sizeof(buf)`
111
 * @offset: offset in bytes into @buf where sum should start
112
 * @n: number of bytes to sum from @buf
113
 * @value: (out) (nullable): the result
114
 * @error: (nullable): optional return location for an error
115
 *
116
 * Returns the arithmetic sum of all bytes in @buf, adding them one byte at a time.
117
 *
118
 * You don't need to use this function in "obviously correct" cases, nor should
119
 * you use it when performance is a concern. Only use it when you're not sure if
120
 * malicious data from a device or firmware could cause memory corruption.
121
 *
122
 * Returns: %TRUE on success, %FALSE otherwise
123
 *
124
 * Since: 2.1.2
125
 **/
126
gboolean
127
fu_sum16_safe(const guint8 *buf, gsize bufsz, gsize offset, gsize n, guint16 *value, GError **error)
128
0
{
129
0
  g_return_val_if_fail(buf != NULL || bufsz == 0, FALSE);
130
0
  g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
131
132
0
  if (!fu_memchk_read(bufsz, offset, n, error))
133
0
    return FALSE;
134
0
  if (value != NULL)
135
0
    *value = fu_sum16(buf + offset, n);
136
0
  return TRUE;
137
0
}
138
139
/**
140
 * fu_sum16_bytes:
141
 * @blob: a #GBytes
142
 *
143
 * Returns the arithmetic sum of all bytes in @blob, adding them one byte at a time.
144
 *
145
 * Returns: sum value
146
 *
147
 * Since: 1.8.2
148
 **/
149
guint16
150
fu_sum16_bytes(GBytes *blob)
151
0
{
152
0
  g_return_val_if_fail(blob != NULL, G_MAXUINT16);
153
0
  return fu_sum16(g_bytes_get_data(blob, NULL), g_bytes_get_size(blob));
154
0
}
155
156
/**
157
 * fu_sum16w:
158
 * @buf: memory buffer
159
 * @bufsz: size of @buf
160
 * @endian: an endian type, e.g. %G_LITTLE_ENDIAN
161
 *
162
 * Returns the arithmetic sum of all bytes in @buf, adding them one word at a time.
163
 * The caller must ensure that @bufsz is a multiple of 2.
164
 *
165
 * Returns: sum value
166
 *
167
 * Since: 1.8.2
168
 **/
169
guint16
170
fu_sum16w(const guint8 *buf, gsize bufsz, FuEndianType endian)
171
3.24k
{
172
3.24k
  guint16 checksum = 0;
173
3.24k
  g_return_val_if_fail(buf != NULL || bufsz == 0, G_MAXUINT16);
174
3.24k
  g_return_val_if_fail(bufsz % 2 == 0, G_MAXUINT16);
175
119k
  for (gsize i = 0; i < bufsz; i += 2)
176
116k
    checksum += fu_memread_uint16(&buf[i], endian);
177
3.24k
  return checksum;
178
3.24k
}
179
180
/**
181
 * fu_sum16w_bytes:
182
 * @blob: a #GBytes
183
 * @endian: an endian type, e.g. %G_LITTLE_ENDIAN
184
 *
185
 * Returns the arithmetic sum of all bytes in @blob, adding them one word at a time.
186
 * The caller must ensure that the size of @blob is a multiple of 2.
187
 *
188
 * Returns: sum value
189
 *
190
 * Since: 1.8.2
191
 **/
192
guint16
193
fu_sum16w_bytes(GBytes *blob, FuEndianType endian)
194
0
{
195
0
  g_return_val_if_fail(blob != NULL, G_MAXUINT16);
196
0
  return fu_sum16w(g_bytes_get_data(blob, NULL), g_bytes_get_size(blob), endian);
197
0
}
198
199
/**
200
 * fu_sum32:
201
 * @buf: memory buffer
202
 * @bufsz: size of @buf
203
 *
204
 * Returns the arithmetic sum of all bytes in @buf, adding them one byte at a time.
205
 *
206
 * Returns: sum value
207
 *
208
 * Since: 1.8.2
209
 **/
210
guint32
211
fu_sum32(const guint8 *buf, gsize bufsz)
212
0
{
213
0
  guint32 checksum = 0;
214
0
  g_return_val_if_fail(buf != NULL || bufsz == 0, G_MAXUINT32);
215
0
  for (gsize i = 0; i < bufsz; i++)
216
0
    checksum += buf[i];
217
0
  return checksum;
218
0
}
219
220
/**
221
 * fu_sum32_bytes:
222
 * @blob: a #GBytes
223
 *
224
 * Returns the arithmetic sum of all bytes in @blob, adding them one byte at a time.
225
 *
226
 * Returns: sum value
227
 *
228
 * Since: 1.8.2
229
 **/
230
guint32
231
fu_sum32_bytes(GBytes *blob)
232
0
{
233
0
  g_return_val_if_fail(blob != NULL, G_MAXUINT32);
234
0
  return fu_sum32(g_bytes_get_data(blob, NULL), g_bytes_get_size(blob));
235
0
}
236
237
/**
238
 * fu_sum32w:
239
 * @buf: memory buffer
240
 * @bufsz: size of @buf
241
 * @endian: an endian type, e.g. %G_LITTLE_ENDIAN
242
 *
243
 * Returns the arithmetic sum of all bytes in @buf, adding them one dword at a time.
244
 * The caller must ensure that @bufsz is a multiple of 4.
245
 *
246
 * Returns: sum value
247
 *
248
 * Since: 1.8.2
249
 **/
250
guint32
251
fu_sum32w(const guint8 *buf, gsize bufsz, FuEndianType endian)
252
0
{
253
0
  guint32 checksum = 0;
254
0
  g_return_val_if_fail(buf != NULL || bufsz == 0, G_MAXUINT32);
255
0
  g_return_val_if_fail(bufsz % 4 == 0, G_MAXUINT32);
256
0
  for (gsize i = 0; i < bufsz; i += 4)
257
0
    checksum += fu_memread_uint32(&buf[i], endian);
258
0
  return checksum;
259
0
}
260
261
/**
262
 * fu_sum32w_bytes:
263
 * @blob: a #GBytes
264
 * @endian: an endian type, e.g. %G_LITTLE_ENDIAN
265
 *
266
 * Returns the arithmetic sum of all bytes in @blob, adding them one dword at a time.
267
 * The caller must ensure that the size of @blob is a multiple of 4.
268
 *
269
 * Returns: sum value
270
 *
271
 * Since: 1.8.2
272
 **/
273
guint32
274
fu_sum32w_bytes(GBytes *blob, FuEndianType endian)
275
0
{
276
0
  g_return_val_if_fail(blob != NULL, G_MAXUINT32);
277
0
  return fu_sum32w(g_bytes_get_data(blob, NULL), g_bytes_get_size(blob), endian);
278
0
}