Coverage Report

Created: 2025-08-03 06:38

/src/upx/src/options.cpp
Line
Count
Source (jump to first uncovered line)
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
70.8k
void Options::reset() noexcept {
43
70.8k
#define opt ERROR_DO_NOT_USE_opt // self-protect against using the wrong variable
44
70.8k
    Options *const o = this;
45
70.8k
    mem_clear(o);
46
70.8k
    o->crp.reset();
47
48
70.8k
    o->cmd = CMD_NONE;
49
70.8k
    o->method = M_NONE;
50
70.8k
    o->level = -1;
51
70.8k
    o->filter = FT_NONE;
52
53
70.8k
    o->backup = -1;
54
70.8k
    o->overlay = -1;
55
70.8k
    o->preserve_mode = true;
56
70.8k
    o->preserve_ownership = true;
57
70.8k
    o->preserve_timestamp = true;
58
70.8k
    o->verbose = 2;
59
60
70.8k
    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
70.8k
#endif
68
    // support NO_COLOR, see https://no-color.org/
69
    // "... when present and not an empty string (regardless of its value)"
70
70.8k
    const char *e = upx_getenv("NO_COLOR");
71
70.8k
    if (e && e[0])
72
0
        o->console = CON_FILE;
73
74
    // options for various executable formats
75
76
70.8k
    o->o_unix.osabi0 = 3; // 3 == ELFOSABI_LINUX
77
78
70.8k
    o->win32_pe.compress_exports = 1;
79
70.8k
    o->win32_pe.compress_icons = 2;
80
70.8k
    o->win32_pe.compress_resources = -1;
81
1.84M
    for (size_t i = 0; i < TABLESIZE(o->win32_pe.compress_rt); i++)
82
1.77M
        o->win32_pe.compress_rt[i] = -1;
83
70.8k
    o->win32_pe.compress_rt[24] = false; // 24 == RT_MANIFEST
84
70.8k
    o->win32_pe.strip_relocs = -1;
85
70.8k
    o->win32_pe.keep_resource = "";
86
70.8k
#undef opt
87
70.8k
}
88
89
/*************************************************************************
90
// doctest checks
91
**************************************************************************/
92
93
7.08k
TEST_CASE("Options::reset") {
94
7.08k
#define opt ERROR_DO_NOT_USE_opt // self-protect against using the wrong variable
95
7.08k
    COMPILE_TIME_ASSERT(std::is_standard_layout<Options>::value)
96
7.08k
    COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible<Options>::value)
97
7.08k
    COMPILE_TIME_ASSERT(std::is_trivially_copyable<Options>::value)
98
99
7.08k
    Options local_options;
100
7.08k
    Options *const o = &local_options;
101
7.08k
    o->reset();
102
7.08k
    CHECK(o->o_unix.osabi0 == 3);
103
7.08k
    static_assert(TABLESIZE(o->win32_pe.compress_rt) == 25); // 25 == RT_LAST
104
7.08k
    CHECK(o->win32_pe.compress_exports);
105
7.08k
    CHECK(o->win32_pe.compress_icons);
106
7.08k
    CHECK(o->win32_pe.strip_relocs);
107
    // issue 728
108
7.08k
    CHECK(o->win32_pe.compress_resources);
109
177k
    for (size_t i = 0; i < 24; i++)
110
170k
        CHECK(o->win32_pe.compress_rt[i]);
111
7.08k
    CHECK(!o->win32_pe.compress_rt[24]); // 24 == RT_MANIFEST
112
7.08k
#undef opt
113
7.08k
}
114
115
template <size_t N>
116
56.6k
static inline void test_options(const char *(&a)[N]) {
117
56.6k
    (void) main_get_options((int) (N - 1), ACC_UNCONST_CAST(char **, a));
118
56.6k
}
options.cpp:void test_options<4ul>(char const* (&) [4ul])
Line
Count
Source
116
42.5k
static inline void test_options(const char *(&a)[N]) {
117
42.5k
    (void) main_get_options((int) (N - 1), ACC_UNCONST_CAST(char **, a));
118
42.5k
}
options.cpp:void test_options<5ul>(char const* (&) [5ul])
Line
Count
Source
116
14.1k
static inline void test_options(const char *(&a)[N]) {
117
14.1k
    (void) main_get_options((int) (N - 1), ACC_UNCONST_CAST(char **, a));
118
14.1k
}
119
120
56.6k
TEST_CASE("getopt") {
121
#if WITH_THREADS
122
    std::lock_guard<std::mutex> lock(opt_lock_mutex);
123
#endif
124
56.6k
    Options *const saved_opt = opt;
125
56.6k
    Options local_options;
126
56.6k
    opt = &local_options;
127
56.6k
    opt->reset();
128
56.6k
    opt->debug.getopt_throw_instead_of_exit = true;
129
56.6k
    static const char a0[] = "<argv0>";
130
131
56.6k
    SUBCASE("issue 587") {
132
7.08k
        const char *a[] = {a0, "--brute", "--lzma", nullptr};
133
7.08k
        test_options(a);
134
7.08k
        CHECK(opt->all_methods);
135
7.08k
        CHECK(opt->all_methods_use_lzma == 1);
136
7.08k
    }
137
56.6k
    SUBCASE("issue 587") {
138
7.08k
        const char *a[] = {a0, "--lzma", "--brute", nullptr};
139
7.08k
        test_options(a);
140
7.08k
        CHECK(opt->all_methods);
141
7.08k
        CHECK(opt->all_methods_use_lzma == 1);
142
7.08k
    }
143
56.6k
    SUBCASE("issue 587") {
144
7.08k
        const char *a[] = {a0, "--brute", "--no-lzma", nullptr};
145
7.08k
        test_options(a);
146
7.08k
        CHECK(opt->all_methods);
147
7.08k
        CHECK(opt->all_methods_use_lzma == -1);
148
7.08k
    }
149
56.6k
    SUBCASE("issue 587") {
150
7.08k
        const char *a[] = {a0, "--no-lzma", "--brute", nullptr};
151
7.08k
        test_options(a);
152
7.08k
        CHECK(opt->all_methods);
153
7.08k
        CHECK(opt->all_methods_use_lzma == -1);
154
7.08k
    }
155
56.6k
    SUBCASE("issue 587") {
156
7.08k
        const char *a[] = {a0, "--no-lzma", "--lzma", nullptr};
157
7.08k
        test_options(a);
158
7.08k
        CHECK(!opt->all_methods);
159
7.08k
        CHECK(opt->all_methods_use_lzma == 1);
160
7.08k
        CHECK(opt->method == M_LZMA);
161
7.08k
    }
162
56.6k
    SUBCASE("issue 587") {
163
7.08k
        const char *a[] = {a0, "--no-lzma", "--lzma", "--brute", nullptr};
164
7.08k
        test_options(a);
165
7.08k
        CHECK(opt->all_methods);
166
7.08k
        CHECK(opt->all_methods_use_lzma == 1);
167
7.08k
        CHECK(opt->method == -1);
168
7.08k
    }
169
56.6k
    SUBCASE("issue 587") {
170
7.08k
        const char *a[] = {a0, "--lzma", "--no-lzma", nullptr};
171
7.08k
        test_options(a);
172
7.08k
        CHECK(!opt->all_methods);
173
7.08k
        CHECK(opt->all_methods_use_lzma == -1);
174
7.08k
        CHECK(opt->method == -1);
175
7.08k
    }
176
56.6k
    SUBCASE("issue 587") {
177
7.08k
        const char *a[] = {a0, "--lzma", "--no-lzma", "--brute", nullptr};
178
7.08k
        test_options(a);
179
7.08k
        CHECK(opt->all_methods);
180
7.08k
        CHECK(opt->all_methods_use_lzma == -1);
181
7.08k
        CHECK(opt->method == -1);
182
7.08k
    }
183
184
56.6k
    opt = saved_opt;
185
56.6k
}
186
187
/* vim:set ts=4 sw=4 et: */