Coverage Report

Created: 2026-10-17 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-lzma-common.c
Line
Count
Source
1
/*
2
 * Copyright 2021 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include <lzma.h>
10
11
#include "fu-common.h"
12
#include "fu-lzma-common.h"
13
14
/**
15
 * fu_lzma_decompress_bytes:
16
 * @blob: data
17
 * @memlimit: decompression memory limit, in bytes
18
 * @error: (nullable): optional return location for an error
19
 *
20
 * Decompresses a LZMA stream.
21
 *
22
 * Returns: (transfer full): decompressed data
23
 *
24
 * Since: 2.0.7
25
 **/
26
GBytes *
27
fu_lzma_decompress_bytes(GBytes *blob, guint64 memlimit, GError **error)
28
974
{
29
974
  const gsize tmpbufsz = 0x20000;
30
974
  lzma_ret rc;
31
974
  lzma_stream strm = LZMA_STREAM_INIT;
32
974
  g_autofree guint8 *tmpbuf = g_malloc0(tmpbufsz);
33
974
  g_autoptr(GByteArray) buf = g_byte_array_new();
34
35
974
  strm.next_in = g_bytes_get_data(blob, NULL);
36
974
  strm.avail_in = g_bytes_get_size(blob);
37
38
974
  rc = lzma_auto_decoder(&strm, memlimit, LZMA_TELL_UNSUPPORTED_CHECK);
39
974
  if (rc != LZMA_OK) {
40
0
    lzma_end(&strm);
41
0
    g_set_error(error,
42
0
          FWUPD_ERROR,
43
0
          FWUPD_ERROR_NOT_SUPPORTED,
44
0
          "failed to set up LZMA decoder rc=%u",
45
0
          rc);
46
0
    return NULL;
47
0
  }
48
1.44k
  do {
49
1.44k
    strm.next_out = tmpbuf;
50
1.44k
    strm.avail_out = tmpbufsz;
51
1.44k
    rc = lzma_code(&strm, LZMA_RUN);
52
1.44k
    if (rc != LZMA_OK && rc != LZMA_STREAM_END)
53
596
      break;
54
850
    if (buf->len + tmpbufsz > 2 * FU_GB) {
55
0
      rc = LZMA_BUF_ERROR;
56
0
      break;
57
0
    }
58
850
    g_byte_array_append(buf, tmpbuf, tmpbufsz - strm.avail_out);
59
850
  } while (rc == LZMA_OK);
60
974
  lzma_end(&strm);
61
62
  /* success */
63
974
  if (rc != LZMA_OK && rc != LZMA_STREAM_END) {
64
596
    g_set_error(error,
65
596
          FWUPD_ERROR,
66
596
          FWUPD_ERROR_NOT_SUPPORTED,
67
596
          "failed to decode LZMA data rc=%u",
68
596
          rc);
69
596
    return NULL;
70
596
  }
71
378
  return g_bytes_new(buf->data, buf->len);
72
974
}
73
74
/**
75
 * fu_lzma_compress_bytes:
76
 * @blob: data
77
 * @error: (nullable): optional return location for an error
78
 *
79
 * Compresses into a LZMA stream.
80
 *
81
 * Returns: (transfer full): compressed data
82
 *
83
 * Since: 1.9.8
84
 **/
85
GBytes *
86
fu_lzma_compress_bytes(GBytes *blob, GError **error)
87
0
{
88
0
  const gsize tmpbufsz = 0x20000;
89
0
  lzma_ret rc;
90
0
  lzma_stream strm = LZMA_STREAM_INIT;
91
0
  g_autofree guint8 *tmpbuf = g_malloc0(tmpbufsz);
92
0
  g_autoptr(GByteArray) buf = g_byte_array_new();
93
94
0
  strm.next_in = g_bytes_get_data(blob, NULL);
95
0
  strm.avail_in = g_bytes_get_size(blob);
96
97
  /* xz default compression level is 6, higher values increase CPU and memory usage */
98
0
  rc = lzma_easy_encoder(&strm, 6, LZMA_CHECK_CRC64);
99
0
  if (rc != LZMA_OK) {
100
0
    lzma_end(&strm);
101
0
    g_set_error(error,
102
0
          FWUPD_ERROR,
103
0
          FWUPD_ERROR_NOT_SUPPORTED,
104
0
          "failed to set up LZMA encoder rc=%u",
105
0
          rc);
106
0
    return NULL;
107
0
  }
108
0
  do {
109
0
    strm.next_out = tmpbuf;
110
0
    strm.avail_out = tmpbufsz;
111
0
    rc = lzma_code(&strm, LZMA_FINISH);
112
0
    if (rc != LZMA_OK && rc != LZMA_STREAM_END)
113
0
      break;
114
0
    g_byte_array_append(buf, tmpbuf, tmpbufsz - strm.avail_out);
115
0
  } while (rc == LZMA_OK);
116
0
  lzma_end(&strm);
117
118
  /* success */
119
0
  if (rc != LZMA_OK && rc != LZMA_STREAM_END) {
120
0
    g_set_error(error,
121
0
          FWUPD_ERROR,
122
0
          FWUPD_ERROR_NOT_SUPPORTED,
123
0
          "failed to encode LZMA data rc=%u",
124
0
          rc);
125
0
    return NULL;
126
0
  }
127
0
  return g_bytes_new(buf->data, buf->len);
128
0
}