Coverage Report

Created: 2026-04-28 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-json-firmware.c
Line
Count
Source
1
/*
2
 * Copyright 2025 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-common.h"
12
#include "fu-json-firmware.h"
13
14
/**
15
 * FuJsonFirmware:
16
 *
17
 * A "dummy" loader that just checks if the file can be parsed and written as JSON format.
18
 */
19
20
typedef struct {
21
  FwupdJsonNode *json_node;
22
} FuJsonFirmwarePrivate;
23
24
7.78k
G_DEFINE_TYPE_WITH_PRIVATE(FuJsonFirmware, fu_json_firmware, FU_TYPE_FIRMWARE)
25
7.78k
#define GET_PRIVATE(o) (fu_json_firmware_get_instance_private(o))
26
27
static gboolean
28
fu_json_firmware_parse(FuFirmware *firmware,
29
           GInputStream *stream,
30
           FuFirmwareParseFlags flags,
31
           GError **error)
32
2.29k
{
33
2.29k
  FuJsonFirmware *self = FU_JSON_FIRMWARE(firmware);
34
2.29k
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
35
2.29k
  g_autoptr(FwupdJsonParser) json_parser = fwupd_json_parser_new();
36
37
2.29k
#ifdef HAVE_FUZZER
38
  /* make the fuzzer spend time on complexity, not depth or length -> OOM */
39
2.29k
  fwupd_json_parser_set_max_depth(json_parser, 5);
40
2.29k
  fwupd_json_parser_set_max_items(json_parser, 10);
41
2.29k
  fwupd_json_parser_set_max_quoted(json_parser, 10);
42
#else
43
  fwupd_json_parser_set_max_depth(json_parser, 50);
44
  fwupd_json_parser_set_max_items(json_parser, 10000);
45
  fwupd_json_parser_set_max_quoted(json_parser, 100000);
46
#endif
47
48
  /* just load into memory, no extraction performed */
49
2.29k
  priv->json_node = fwupd_json_parser_load_from_stream(json_parser,
50
2.29k
                   stream,
51
2.29k
                   FWUPD_JSON_LOAD_FLAG_NONE,
52
2.29k
                   error);
53
2.29k
  if (priv->json_node == NULL)
54
1.39k
    return FALSE;
55
56
  /* success */
57
903
  return TRUE;
58
2.29k
}
59
60
static GByteArray *
61
fu_json_firmware_write(FuFirmware *firmware, GError **error)
62
903
{
63
903
  FuJsonFirmware *self = FU_JSON_FIRMWARE(firmware);
64
903
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
65
903
  g_autoptr(GByteArray) buf = g_byte_array_new();
66
903
  g_autoptr(GString) str = NULL;
67
68
  /* sanity check */
69
903
  if (priv->json_node == NULL) {
70
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_DATA, "no JSON node");
71
0
    return NULL;
72
0
  }
73
74
  /* export with no padding */
75
903
  str = fwupd_json_node_to_string(priv->json_node, FWUPD_JSON_EXPORT_FLAG_NONE);
76
903
  g_byte_array_append(buf, (const guint8 *)str->str, str->len);
77
903
  return g_steal_pointer(&buf);
78
903
}
79
80
static void
81
fu_json_firmware_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
82
0
{
83
0
  FuJsonFirmware *self = FU_JSON_FIRMWARE(firmware);
84
0
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
85
0
  if (priv->json_node != NULL) {
86
0
    g_autoptr(GString) str =
87
0
        fwupd_json_node_to_string(priv->json_node, FWUPD_JSON_EXPORT_FLAG_NONE);
88
0
    fu_xmlb_builder_insert_kv(bn, "json", str->str);
89
0
  }
90
0
}
91
92
static gboolean
93
fu_json_firmware_build(FuFirmware *firmware, XbNode *n, GError **error)
94
0
{
95
0
  FuJsonFirmware *self = FU_JSON_FIRMWARE(firmware);
96
0
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
97
0
  const gchar *json;
98
0
  g_autoptr(FwupdJsonParser) json_parser = fwupd_json_parser_new();
99
100
  /* set appropriate limits */
101
0
  fwupd_json_parser_set_max_depth(json_parser, 10);
102
0
  fwupd_json_parser_set_max_items(json_parser, 100);
103
0
  fwupd_json_parser_set_max_quoted(json_parser, 10000);
104
105
  /* simple properties */
106
0
  json = xb_node_query_text(n, "json", error);
107
0
  if (json == NULL) {
108
0
    fwupd_error_convert(error);
109
0
    return FALSE;
110
0
  }
111
0
  priv->json_node =
112
0
      fwupd_json_parser_load_from_data(json_parser, json, FWUPD_JSON_LOAD_FLAG_NONE, error);
113
0
  if (priv->json_node == NULL)
114
0
    return FALSE;
115
116
  /* success */
117
0
  return TRUE;
118
0
}
119
120
static void
121
fu_json_firmware_init(FuJsonFirmware *self)
122
2.29k
{
123
2.29k
  fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_NO_AUTO_DETECTION);
124
2.29k
  fu_firmware_set_size_max(FU_FIRMWARE(self), 128 * FU_MB);
125
2.29k
}
126
127
static void
128
fu_json_firmware_finalize(GObject *obj)
129
2.29k
{
130
2.29k
  FuJsonFirmware *self = FU_JSON_FIRMWARE(obj);
131
2.29k
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
132
2.29k
  if (priv->json_node != NULL)
133
903
    fwupd_json_node_unref(priv->json_node);
134
2.29k
  G_OBJECT_CLASS(fu_json_firmware_parent_class)->finalize(obj);
135
2.29k
}
136
137
static void
138
fu_json_firmware_class_init(FuJsonFirmwareClass *klass)
139
1
{
140
1
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
141
1
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
142
1
  object_class->finalize = fu_json_firmware_finalize;
143
1
  firmware_class->parse = fu_json_firmware_parse;
144
1
  firmware_class->write = fu_json_firmware_write;
145
1
  firmware_class->build = fu_json_firmware_build;
146
1
  firmware_class->export = fu_json_firmware_export;
147
1
}