Coverage Report

Created: 2025-11-24 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-firmware-common.c
Line
Count
Source
1
/*
2
 * Copyright 2015 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#define G_LOG_DOMAIN "FuFirmware"
8
9
#include "config.h"
10
11
#include "fu-firmware-common.h"
12
#include "fu-mem.h"
13
#include "fu-string.h"
14
15
/**
16
 * fu_firmware_strparse_uint4_safe:
17
 * @data: destination buffer
18
 * @datasz: size of @data, typically the same as `strlen(data)`
19
 * @offset: offset in chars into @data to read
20
 * @value: (out) (nullable): parsed value
21
 * @error: (nullable): optional return location for an error
22
 *
23
 * Parses a base 16 number from a string of 1 character in length.
24
 * The returned @value will range from 0 to 0xf.
25
 *
26
 * Returns: %TRUE if parsed, %FALSE otherwise
27
 *
28
 * Since: 1.5.6
29
 **/
30
gboolean
31
fu_firmware_strparse_uint4_safe(const gchar *data,
32
        gsize datasz,
33
        gsize offset,
34
        guint8 *value,
35
        GError **error)
36
2.32k
{
37
2.32k
  gchar buffer[2] = {'\0'};
38
2.32k
  guint64 valuetmp = 0;
39
2.32k
  if (!fu_memcpy_safe((guint8 *)buffer,
40
2.32k
          sizeof(buffer),
41
2.32k
          0x0, /* dst */
42
2.32k
          (const guint8 *)data,
43
2.32k
          datasz,
44
2.32k
          offset, /* src */
45
2.32k
          sizeof(buffer) - 1,
46
2.32k
          error))
47
0
    return FALSE;
48
2.32k
  if (!fu_strtoull(buffer, &valuetmp, 0, 0xF, FU_INTEGER_BASE_16, error)) {
49
4
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
50
4
    g_prefix_error(error, "cannot parse %s as hex: ", str);
51
4
    return FALSE;
52
4
  }
53
2.31k
  if (value != NULL)
54
2.31k
    *value = (guint8)valuetmp;
55
2.31k
  return TRUE;
56
2.32k
}
57
58
/**
59
 * fu_firmware_strparse_uint8_safe:
60
 * @data: destination buffer
61
 * @datasz: size of @data, typically the same as `strlen(data)`
62
 * @offset: offset in chars into @data to read
63
 * @value: (out) (nullable): parsed value
64
 * @error: (nullable): optional return location for an error
65
 *
66
 * Parses a base 16 number from a string of 2 characters in length.
67
 * The returned @value will range from 0 to 0xff.
68
 *
69
 * Returns: %TRUE if parsed, %FALSE otherwise
70
 *
71
 * Since: 1.5.6
72
 **/
73
gboolean
74
fu_firmware_strparse_uint8_safe(const gchar *data,
75
        gsize datasz,
76
        gsize offset,
77
        guint8 *value,
78
        GError **error)
79
4.46M
{
80
4.46M
  gchar buffer[3] = {'\0'};
81
4.46M
  guint64 valuetmp = 0;
82
4.46M
  if (!fu_memcpy_safe((guint8 *)buffer,
83
4.46M
          sizeof(buffer),
84
4.46M
          0x0, /* dst */
85
4.46M
          (const guint8 *)data,
86
4.46M
          datasz,
87
4.46M
          offset, /* src */
88
4.46M
          sizeof(buffer) - 1,
89
4.46M
          error))
90
704
    return FALSE;
91
4.46M
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT8, FU_INTEGER_BASE_16, error)) {
92
521
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
93
521
    g_prefix_error(error, "cannot parse %s as hex: ", str);
94
521
    return FALSE;
95
521
  }
96
4.46M
  if (value != NULL)
97
4.46M
    *value = (guint8)valuetmp;
98
4.46M
  return TRUE;
99
4.46M
}
100
101
/**
102
 * fu_firmware_strparse_uint16_safe:
103
 * @data: destination buffer
104
 * @datasz: size of @data, typically the same as `strlen(data)`
105
 * @offset: offset in chars into @data to read
106
 * @value: (out) (nullable): parsed value
107
 * @error: (nullable): optional return location for an error
108
 *
109
 * Parses a base 16 number from a string of 4 characters in length.
110
 * The returned @value will range from 0 to 0xffff.
111
 *
112
 * Returns: %TRUE if parsed, %FALSE otherwise
113
 *
114
 * Since: 1.5.6
115
 **/
116
gboolean
117
fu_firmware_strparse_uint16_safe(const gchar *data,
118
         gsize datasz,
119
         gsize offset,
120
         guint16 *value,
121
         GError **error)
122
2.41M
{
123
2.41M
  gchar buffer[5] = {'\0'};
124
2.41M
  guint64 valuetmp = 0;
125
2.41M
  if (!fu_memcpy_safe((guint8 *)buffer,
126
2.41M
          sizeof(buffer),
127
2.41M
          0x0, /* dst */
128
2.41M
          (const guint8 *)data,
129
2.41M
          datasz,
130
2.41M
          offset, /* src */
131
2.41M
          sizeof(buffer) - 1,
132
2.41M
          error))
133
140
    return FALSE;
134
2.41M
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT16, FU_INTEGER_BASE_16, error)) {
135
116
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
136
116
    g_prefix_error(error, "cannot parse %s as hex: ", str);
137
116
    return FALSE;
138
116
  }
139
2.41M
  if (value != NULL)
140
2.41M
    *value = (guint16)valuetmp;
141
2.41M
  return TRUE;
142
2.41M
}
143
144
/**
145
 * fu_firmware_strparse_uint24_safe:
146
 * @data: destination buffer
147
 * @datasz: size of @data, typically the same as `strlen(data)`
148
 * @offset: offset in chars into @data to read
149
 * @value: (out) (nullable): parsed value
150
 * @error: (nullable): optional return location for an error
151
 *
152
 * Parses a base 16 number from a string of 6 characters in length.
153
 * The returned @value will range from 0 to 0xffffff.
154
 *
155
 * Returns: %TRUE if parsed, %FALSE otherwise
156
 *
157
 * Since: 1.5.6
158
 **/
159
gboolean
160
fu_firmware_strparse_uint24_safe(const gchar *data,
161
         gsize datasz,
162
         gsize offset,
163
         guint32 *value,
164
         GError **error)
165
7.47k
{
166
7.47k
  gchar buffer[7] = {'\0'};
167
7.47k
  guint64 valuetmp = 0;
168
7.47k
  if (!fu_memcpy_safe((guint8 *)buffer,
169
7.47k
          sizeof(buffer),
170
7.47k
          0x0, /* dst */
171
7.47k
          (const guint8 *)data,
172
7.47k
          datasz,
173
7.47k
          offset, /* src */
174
7.47k
          sizeof(buffer) - 1,
175
7.47k
          error))
176
33
    return FALSE;
177
7.44k
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT32, FU_INTEGER_BASE_16, error)) {
178
29
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
179
29
    g_prefix_error(error, "cannot parse %s as hex: ", str);
180
29
    return FALSE;
181
29
  }
182
7.41k
  if (value != NULL)
183
7.41k
    *value = (guint16)valuetmp;
184
7.41k
  return TRUE;
185
7.44k
}
186
187
/**
188
 * fu_firmware_strparse_uint32_safe:
189
 * @data: destination buffer
190
 * @datasz: size of @data, typically the same as `strlen(data)`
191
 * @offset: offset in chars into @data to read
192
 * @value: (out) (nullable): parsed value
193
 * @error: (nullable): optional return location for an error
194
 *
195
 * Parses a base 16 number from a string of 8 characters in length.
196
 * The returned @value will range from 0 to 0xffffffff.
197
 *
198
 * Returns: %TRUE if parsed, %FALSE otherwise
199
 *
200
 * Since: 1.5.6
201
 **/
202
gboolean
203
fu_firmware_strparse_uint32_safe(const gchar *data,
204
         gsize datasz,
205
         gsize offset,
206
         guint32 *value,
207
         GError **error)
208
10.1k
{
209
10.1k
  gchar buffer[9] = {'\0'};
210
10.1k
  guint64 valuetmp = 0;
211
10.1k
  if (!fu_memcpy_safe((guint8 *)buffer,
212
10.1k
          sizeof(buffer),
213
10.1k
          0x0, /* dst */
214
10.1k
          (const guint8 *)data,
215
10.1k
          datasz,
216
10.1k
          offset, /* src */
217
10.1k
          sizeof(buffer) - 1,
218
10.1k
          error))
219
36
    return FALSE;
220
10.1k
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT32, FU_INTEGER_BASE_16, error)) {
221
186
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
222
186
    g_prefix_error(error, "cannot parse %s as hex: ", str);
223
186
    return FALSE;
224
186
  }
225
9.94k
  if (value != NULL)
226
9.94k
    *value = (guint32)valuetmp;
227
9.94k
  return TRUE;
228
10.1k
}