Coverage Report

Created: 2026-04-12 07:04

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.43k
G_DEFINE_TYPE_WITH_PRIVATE(FuJsonFirmware, fu_json_firmware, FU_TYPE_FIRMWARE)
25
7.43k
#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.18k
{
33
2.18k
  FuJsonFirmware *self = FU_JSON_FIRMWARE(firmware);
34
2.18k
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
35
2.18k
  g_autoptr(FwupdJsonParser) json_parser = fwupd_json_parser_new();
36
37
2.18k
#ifdef HAVE_FUZZER
38
  /* make the fuzzer spend time on complexity, not depth or length -> OOM */
39
2.18k
  fwupd_json_parser_set_max_depth(json_parser, 5);
40
2.18k
  fwupd_json_parser_set_max_items(json_parser, 10);
41
2.18k
  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.18k
  priv->json_node = fwupd_json_parser_load_from_stream(json_parser,
50
2.18k
                   stream,
51
2.18k
                   FWUPD_JSON_LOAD_FLAG_NONE,
52
2.18k
                   error);
53
2.18k
  if (priv->json_node == NULL)
54
1.32k
    return FALSE;
55
56
  /* success */
57
864
  return TRUE;
58
2.18k
}
59
60
static GByteArray *
61
fu_json_firmware_write(FuFirmware *firmware, GError **error)
62
864
{
63
864
  FuJsonFirmware *self = FU_JSON_FIRMWARE(firmware);
64
864
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
65
864
  g_autoptr(GByteArray) buf = g_byte_array_new();
66
864
  g_autoptr(GString) str = NULL;
67
68
  /* sanity check */
69
864
  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
864
  str = fwupd_json_node_to_string(priv->json_node, FWUPD_JSON_EXPORT_FLAG_NONE);
76
864
  g_byte_array_append(buf, (const guint8 *)str->str, str->len);
77
864
  return g_steal_pointer(&buf);
78
864
}
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.18k
{
123
2.18k
  fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_NO_AUTO_DETECTION);
124
2.18k
  fu_firmware_set_size_max(FU_FIRMWARE(self), 128 * FU_MB);
125
2.18k
}
126
127
static void
128
fu_json_firmware_finalize(GObject *obj)
129
2.18k
{
130
2.18k
  FuJsonFirmware *self = FU_JSON_FIRMWARE(obj);
131
2.18k
  FuJsonFirmwarePrivate *priv = GET_PRIVATE(self);
132
2.18k
  if (priv->json_node != NULL)
133
864
    fwupd_json_node_unref(priv->json_node);
134
2.18k
  G_OBJECT_CLASS(fu_json_firmware_parent_class)->finalize(obj);
135
2.18k
}
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
}