Coverage Report

Created: 2026-01-09 07:21

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-lzma-common.h"
12
13
/**
14
 * fu_lzma_decompress_bytes:
15
 * @blob: data
16
 * @memlimit: decompression memory limit, in bytes
17
 * @error: (nullable): optional return location for an error
18
 *
19
 * Decompresses a LZMA stream.
20
 *
21
 * Returns: (transfer full): decompressed data
22
 *
23
 * Since: 2.0.7
24
 **/
25
GBytes *
26
fu_lzma_decompress_bytes(GBytes *blob, guint64 memlimit, GError **error)
27
2.11k
{
28
2.11k
  const gsize tmpbufsz = 0x20000;
29
2.11k
  lzma_ret rc;
30
2.11k
  lzma_stream strm = LZMA_STREAM_INIT;
31
2.11k
  g_autofree guint8 *tmpbuf = g_malloc0(tmpbufsz);
32
2.11k
  g_autoptr(GByteArray) buf = g_byte_array_new();
33
34
2.11k
  strm.next_in = g_bytes_get_data(blob, NULL);
35
2.11k
  strm.avail_in = g_bytes_get_size(blob);
36
37
2.11k
  rc = lzma_auto_decoder(&strm, memlimit, LZMA_TELL_UNSUPPORTED_CHECK);
38
2.11k
  if (rc != LZMA_OK) {
39
0
    lzma_end(&strm);
40
0
    g_set_error(error,
41
0
          FWUPD_ERROR,
42
0
          FWUPD_ERROR_NOT_SUPPORTED,
43
0
          "failed to set up LZMA decoder rc=%u",
44
0
          rc);
45
0
    return NULL;
46
0
  }
47
5.11k
  do {
48
5.11k
    strm.next_out = tmpbuf;
49
5.11k
    strm.avail_out = tmpbufsz;
50
5.11k
    rc = lzma_code(&strm, LZMA_RUN);
51
5.11k
    if (rc != LZMA_OK && rc != LZMA_STREAM_END)
52
704
      break;
53
4.40k
    g_byte_array_append(buf, tmpbuf, tmpbufsz - strm.avail_out);
54
4.40k
  } while (rc == LZMA_OK);
55
2.11k
  lzma_end(&strm);
56
57
  /* success */
58
2.11k
  if (rc != LZMA_OK && rc != LZMA_STREAM_END) {
59
704
    g_set_error(error,
60
704
          FWUPD_ERROR,
61
704
          FWUPD_ERROR_NOT_SUPPORTED,
62
704
          "failed to decode LZMA data rc=%u",
63
704
          rc);
64
704
    return NULL;
65
704
  }
66
1.41k
  return g_bytes_new(buf->data, buf->len);
67
2.11k
}
68
69
/**
70
 * fu_lzma_compress_bytes:
71
 * @blob: data
72
 * @error: (nullable): optional return location for an error
73
 *
74
 * Compresses into a LZMA stream.
75
 *
76
 * Returns: (transfer full): compressed data
77
 *
78
 * Since: 1.9.8
79
 **/
80
GBytes *
81
fu_lzma_compress_bytes(GBytes *blob, GError **error)
82
682
{
83
682
  const gsize tmpbufsz = 0x20000;
84
682
  lzma_ret rc;
85
682
  lzma_stream strm = LZMA_STREAM_INIT;
86
682
  g_autofree guint8 *tmpbuf = g_malloc0(tmpbufsz);
87
682
  g_autoptr(GByteArray) buf = g_byte_array_new();
88
89
682
  strm.next_in = g_bytes_get_data(blob, NULL);
90
682
  strm.avail_in = g_bytes_get_size(blob);
91
92
  /* xz default compression level is 6, higher values increase CPU and memory usage */
93
682
  rc = lzma_easy_encoder(&strm, 6, LZMA_CHECK_CRC64);
94
682
  if (rc != LZMA_OK) {
95
0
    lzma_end(&strm);
96
0
    g_set_error(error,
97
0
          FWUPD_ERROR,
98
0
          FWUPD_ERROR_NOT_SUPPORTED,
99
0
          "failed to set up LZMA encoder rc=%u",
100
0
          rc);
101
0
    return NULL;
102
0
  }
103
682
  do {
104
682
    strm.next_out = tmpbuf;
105
682
    strm.avail_out = tmpbufsz;
106
682
    rc = lzma_code(&strm, LZMA_FINISH);
107
682
    if (rc != LZMA_OK && rc != LZMA_STREAM_END)
108
0
      break;
109
682
    g_byte_array_append(buf, tmpbuf, tmpbufsz - strm.avail_out);
110
682
  } while (rc == LZMA_OK);
111
682
  lzma_end(&strm);
112
113
  /* success */
114
682
  if (rc != LZMA_OK && rc != LZMA_STREAM_END) {
115
0
    g_set_error(error,
116
0
          FWUPD_ERROR,
117
0
          FWUPD_ERROR_NOT_SUPPORTED,
118
0
          "failed to encode LZMA data rc=%u",
119
0
          rc);
120
0
    return NULL;
121
0
  }
122
682
  return g_bytes_new(buf->data, buf->len);
123
682
}