Coverage Report

Created: 2025-10-10 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/upx/src/options.cpp
Line
Count
Source
1
/* options.cpp --
2
3
   This file is part of the UPX executable compressor.
4
5
   Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer
6
   Copyright (C) 1996-2025 Laszlo Molnar
7
   All Rights Reserved.
8
9
   UPX and the UCL library are free software; you can redistribute them
10
   and/or modify them under the terms of the GNU General Public License as
11
   published by the Free Software Foundation; either version 2 of
12
   the License, or (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program; see the file COPYING.
21
   If not, write to the Free Software Foundation, Inc.,
22
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24
   Markus F.X.J. Oberhumer              Laszlo Molnar
25
   <markus@oberhumer.com>               <ezerotven+github@gmail.com>
26
 */
27
28
#include "conf.h"
29
30
static Options global_options;
31
// also see class PackMaster for per-file local options
32
Options *opt = &global_options;
33
34
#if WITH_THREADS
35
std::mutex opt_lock_mutex; // for locking "opt"
36
#endif
37
38
/*************************************************************************
39
// reset
40
**************************************************************************/
41
42
57.1k
void Options::reset() noexcept {
43
57.1k
#define opt ERROR_DO_NOT_USE_opt // self-protect against using the wrong variable
44
57.1k
    Options *const o = this;
45
57.1k
    mem_clear(o);
46
57.1k
    o->crp.reset();
47
48
57.1k
    o->cmd = CMD_NONE;
49
57.1k
    o->method = M_NONE;
50
57.1k
    o->level = -1;
51
57.1k
    o->filter = FT_NONE;
52
53
57.1k
    o->backup = -1;
54
57.1k
    o->overlay = -1;
55
57.1k
    o->preserve_mode = true;
56
57.1k
    o->preserve_ownership = true;
57
57.1k
    o->preserve_timestamp = true;
58
57.1k
    o->verbose = 2;
59
60
57.1k
    o->console = CON_FILE;
61
#if (ACC_OS_DOS32) && defined(__DJGPP__)
62
    o->console = CON_INIT;
63
#elif (USE_SCREEN_WIN32)
64
    o->console = CON_INIT;
65
#elif 1 && defined(__linux__)
66
    o->console = CON_INIT;
67
57.1k
#endif
68
    // support NO_COLOR, see https://no-color.org/
69
    // "... when present and not an empty string (regardless of its value)"
70
57.1k
    const char *e = upx_getenv("NO_COLOR");
71
57.1k
    if (e && e[0])
72
0
        o->console = CON_FILE;
73
74
    // options for various executable formats
75
76
57.1k
    o->o_unix.osabi0 = 3; // 3 == ELFOSABI_LINUX
77
78
57.1k
    o->win32_pe.compress_exports = 1;
79
57.1k
    o->win32_pe.compress_icons = 2;
80
57.1k
    o->win32_pe.compress_resources = -1;
81
1.48M
    for (size_t i = 0; i < TABLESIZE(o->win32_pe.compress_rt); i++)
82
1.42M
        o->win32_pe.compress_rt[i] = -1;
83
57.1k
    o->win32_pe.compress_rt[24] = false; // 24 == RT_MANIFEST
84
57.1k
    o->win32_pe.strip_relocs = -1;
85
57.1k
    o->win32_pe.keep_resource = "";
86
57.1k
#undef opt
87
57.1k
}
88
89
/*************************************************************************
90
// doctest checks
91
**************************************************************************/
92
93
5.71k
TEST_CASE("Options::reset") {
94
5.71k
#define opt ERROR_DO_NOT_USE_opt // self-protect against using the wrong variable
95
5.71k
    COMPILE_TIME_ASSERT(std::is_standard_layout<Options>::value)
96
5.71k
    COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible<Options>::value)
97
5.71k
    COMPILE_TIME_ASSERT(std::is_trivially_copyable<Options>::value)
98
99
5.71k
    Options local_options;
100
5.71k
    Options *const o = &local_options;
101
5.71k
    o->reset();
102
5.71k
    CHECK(o->o_unix.osabi0 == 3);
103
5.71k
    static_assert(TABLESIZE(o->win32_pe.compress_rt) == 25); // 25 == RT_LAST
104
5.71k
    CHECK(o->win32_pe.compress_exports);
105
5.71k
    CHECK(o->win32_pe.compress_icons);
106
5.71k
    CHECK(o->win32_pe.strip_relocs);
107
    // issue 728
108
5.71k
    CHECK(o->win32_pe.compress_resources);
109
142k
    for (size_t i = 0; i < 24; i++)
110
137k
        CHECK(o->win32_pe.compress_rt[i]);
111
5.71k
    CHECK(!o->win32_pe.compress_rt[24]); // 24 == RT_MANIFEST
112
5.71k
#undef opt
113
5.71k
}
114
115
template <size_t N>
116
45.7k
static inline void test_options(const char *(&a)[N]) {
117
45.7k
    (void) main_get_options((int) (N - 1), ACC_UNCONST_CAST(char **, a));
118
45.7k
}
options.cpp:void test_options<4ul>(char const* (&) [4ul])
Line
Count
Source
116
34.3k
static inline void test_options(const char *(&a)[N]) {
117
34.3k
    (void) main_get_options((int) (N - 1), ACC_UNCONST_CAST(char **, a));
118
34.3k
}
options.cpp:void test_options<5ul>(char const* (&) [5ul])
Line
Count
Source
116
11.4k
static inline void test_options(const char *(&a)[N]) {
117
11.4k
    (void) main_get_options((int) (N - 1), ACC_UNCONST_CAST(char **, a));
118
11.4k
}
119
120
45.7k
TEST_CASE("getopt") {
121
#if WITH_THREADS
122
    std::lock_guard<std::mutex> lock(opt_lock_mutex);
123
#endif
124
45.7k
    Options *const saved_opt = opt;
125
45.7k
    Options local_options;
126
45.7k
    opt = &local_options;
127
45.7k
    opt->reset();
128
45.7k
    opt->debug.getopt_throw_instead_of_exit = true;
129
45.7k
    static const char a0[] = "<argv0>";
130
131
45.7k
    SUBCASE("issue 587") {
132
5.71k
        const char *a[] = {a0, "--brute", "--lzma", nullptr};
133
5.71k
        test_options(a);
134
5.71k
        CHECK(opt->all_methods);
135
5.71k
        CHECK(opt->all_methods_use_lzma == 1);
136
5.71k
    }
137
45.7k
    SUBCASE("issue 587") {
138
5.71k
        const char *a[] = {a0, "--lzma", "--brute", nullptr};
139
5.71k
        test_options(a);
140
5.71k
        CHECK(opt->all_methods);
141
5.71k
        CHECK(opt->all_methods_use_lzma == 1);
142
5.71k
    }
143
45.7k
    SUBCASE("issue 587") {
144
5.71k
        const char *a[] = {a0, "--brute", "--no-lzma", nullptr};
145
5.71k
        test_options(a);
146
5.71k
        CHECK(opt->all_methods);
147
5.71k
        CHECK(opt->all_methods_use_lzma == -1);
148
5.71k
    }
149
45.7k
    SUBCASE("issue 587") {
150
5.71k
        const char *a[] = {a0, "--no-lzma", "--brute", nullptr};
151
5.71k
        test_options(a);
152
5.71k
        CHECK(opt->all_methods);
153
5.71k
        CHECK(opt->all_methods_use_lzma == -1);
154
5.71k
    }
155
45.7k
    SUBCASE("issue 587") {
156
5.71k
        const char *a[] = {a0, "--no-lzma", "--lzma", nullptr};
157
5.71k
        test_options(a);
158
5.71k
        CHECK(!opt->all_methods);
159
5.71k
        CHECK(opt->all_methods_use_lzma == 1);
160
5.71k
        CHECK(opt->method == M_LZMA);
161
5.71k
    }
162
45.7k
    SUBCASE("issue 587") {
163
5.71k
        const char *a[] = {a0, "--no-lzma", "--lzma", "--brute", nullptr};
164
5.71k
        test_options(a);
165
5.71k
        CHECK(opt->all_methods);
166
5.71k
        CHECK(opt->all_methods_use_lzma == 1);
167
5.71k
        CHECK(opt->method == -1);
168
5.71k
    }
169
45.7k
    SUBCASE("issue 587") {
170
5.71k
        const char *a[] = {a0, "--lzma", "--no-lzma", nullptr};
171
5.71k
        test_options(a);
172
5.71k
        CHECK(!opt->all_methods);
173
5.71k
        CHECK(opt->all_methods_use_lzma == -1);
174
5.71k
        CHECK(opt->method == -1);
175
5.71k
    }
176
45.7k
    SUBCASE("issue 587") {
177
5.71k
        const char *a[] = {a0, "--lzma", "--no-lzma", "--brute", nullptr};
178
5.71k
        test_options(a);
179
5.71k
        CHECK(opt->all_methods);
180
5.71k
        CHECK(opt->all_methods_use_lzma == -1);
181
5.71k
        CHECK(opt->method == -1);
182
5.71k
    }
183
184
45.7k
    opt = saved_opt;
185
45.7k
}
186
187
/* vim:set ts=4 sw=4 et: */