Coverage Report

Created: 2026-01-17 07:04

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.18k
{
37
2.18k
  gchar buffer[2] = {'\0'};
38
2.18k
  guint64 valuetmp = 0;
39
2.18k
  if (!fu_memcpy_safe((guint8 *)buffer,
40
2.18k
          sizeof(buffer),
41
2.18k
          0x0, /* dst */
42
2.18k
          (const guint8 *)data,
43
2.18k
          datasz,
44
2.18k
          offset, /* src */
45
2.18k
          sizeof(buffer) - 1,
46
2.18k
          error))
47
0
    return FALSE;
48
2.18k
  if (!fu_strtoull(buffer, &valuetmp, 0, 0xF, FU_INTEGER_BASE_16, error)) {
49
6
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
50
6
    g_prefix_error(error, "cannot parse %s as hex: ", str);
51
6
    return FALSE;
52
6
  }
53
2.18k
  if (value != NULL)
54
2.18k
    *value = (guint8)valuetmp;
55
2.18k
  return TRUE;
56
2.18k
}
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
5.66M
{
80
5.66M
  gchar buffer[3] = {'\0'};
81
5.66M
  guint64 valuetmp = 0;
82
5.66M
  if (!fu_memcpy_safe((guint8 *)buffer,
83
5.66M
          sizeof(buffer),
84
5.66M
          0x0, /* dst */
85
5.66M
          (const guint8 *)data,
86
5.66M
          datasz,
87
5.66M
          offset, /* src */
88
5.66M
          sizeof(buffer) - 1,
89
5.66M
          error))
90
696
    return FALSE;
91
5.66M
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT8, FU_INTEGER_BASE_16, error)) {
92
534
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
93
534
    g_prefix_error(error, "cannot parse %s as hex: ", str);
94
534
    return FALSE;
95
534
  }
96
5.66M
  if (value != NULL)
97
5.66M
    *value = (guint8)valuetmp;
98
5.66M
  return TRUE;
99
5.66M
}
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.93M
{
123
2.93M
  gchar buffer[5] = {'\0'};
124
2.93M
  guint64 valuetmp = 0;
125
2.93M
  if (!fu_memcpy_safe((guint8 *)buffer,
126
2.93M
          sizeof(buffer),
127
2.93M
          0x0, /* dst */
128
2.93M
          (const guint8 *)data,
129
2.93M
          datasz,
130
2.93M
          offset, /* src */
131
2.93M
          sizeof(buffer) - 1,
132
2.93M
          error))
133
143
    return FALSE;
134
2.93M
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT16, FU_INTEGER_BASE_16, error)) {
135
150
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
136
150
    g_prefix_error(error, "cannot parse %s as hex: ", str);
137
150
    return FALSE;
138
150
  }
139
2.93M
  if (value != NULL)
140
2.93M
    *value = (guint16)valuetmp;
141
2.93M
  return TRUE;
142
2.93M
}
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
8.59k
{
166
8.59k
  gchar buffer[7] = {'\0'};
167
8.59k
  guint64 valuetmp = 0;
168
8.59k
  if (!fu_memcpy_safe((guint8 *)buffer,
169
8.59k
          sizeof(buffer),
170
8.59k
          0x0, /* dst */
171
8.59k
          (const guint8 *)data,
172
8.59k
          datasz,
173
8.59k
          offset, /* src */
174
8.59k
          sizeof(buffer) - 1,
175
8.59k
          error))
176
36
    return FALSE;
177
8.56k
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT32, FU_INTEGER_BASE_16, error)) {
178
31
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
179
31
    g_prefix_error(error, "cannot parse %s as hex: ", str);
180
31
    return FALSE;
181
31
  }
182
8.52k
  if (value != NULL)
183
8.52k
    *value = (guint16)valuetmp;
184
8.52k
  return TRUE;
185
8.56k
}
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.0k
{
209
10.0k
  gchar buffer[9] = {'\0'};
210
10.0k
  guint64 valuetmp = 0;
211
10.0k
  if (!fu_memcpy_safe((guint8 *)buffer,
212
10.0k
          sizeof(buffer),
213
10.0k
          0x0, /* dst */
214
10.0k
          (const guint8 *)data,
215
10.0k
          datasz,
216
10.0k
          offset, /* src */
217
10.0k
          sizeof(buffer) - 1,
218
10.0k
          error))
219
29
    return FALSE;
220
10.0k
  if (!fu_strtoull(buffer, &valuetmp, 0, G_MAXUINT32, FU_INTEGER_BASE_16, error)) {
221
181
    g_autofree gchar *str = fu_strsafe(buffer, sizeof(buffer));
222
181
    g_prefix_error(error, "cannot parse %s as hex: ", str);
223
181
    return FALSE;
224
181
  }
225
9.87k
  if (value != NULL)
226
9.87k
    *value = (guint32)valuetmp;
227
9.87k
  return TRUE;
228
10.0k
}