Coverage Report

Created: 2026-01-09 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/upx/src/p_lx_sh.cpp
Line
Count
Source
1
/* p_lx_sh.cpp --
2
3
   This file is part of the UPX executable compressor.
4
5
   Copyright (C) Markus Franz Xaver Johannes Oberhumer
6
   Copyright (C) Laszlo Molnar
7
   Copyright (C) John F. Reiser
8
   All Rights Reserved.
9
10
   UPX and the UCL library are free software; you can redistribute them
11
   and/or modify them under the terms of the GNU General Public License as
12
   published by the Free Software Foundation; either version 2 of
13
   the License, or (at your option) any later version.
14
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
20
   You should have received a copy of the GNU General Public License
21
   along with this program; see the file COPYING.
22
   If not, write to the Free Software Foundation, Inc.,
23
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25
   Markus F.X.J. Oberhumer              Laszlo Molnar
26
   <markus@oberhumer.com>               <ezerotven+github@gmail.com>
27
28
   John F. Reiser
29
   <jreiser@users.sourceforge.net>
30
 */
31
32
33
#include "conf.h"
34
35
#include "file.h"
36
#include "filter.h"
37
#include "packer.h"
38
#include "p_elf.h"
39
#include "p_unix.h"
40
#include "p_lx_exc.h"
41
#include "p_lx_sh.h"
42
43
#define PT_LOAD     Elf_LE32_Phdr::PT_LOAD
44
45
46
/*************************************************************************
47
//
48
**************************************************************************/
49
50
static const CLANG_FORMAT_DUMMY_STATEMENT
51
#include "stub/i386-linux.elf.shell-entry.h"
52
static const CLANG_FORMAT_DUMMY_STATEMENT
53
#include "stub/i386-linux.elf.shell-fold.h"
54
55
56
PackLinuxI386sh::PackLinuxI386sh(InputFile *f) :
57
11.5k
    super(f), o_shname(0), l_shname(0)
58
11.5k
{
59
11.5k
}
60
61
PackLinuxI386sh::~PackLinuxI386sh()
62
11.5k
{
63
11.5k
}
64
65
void
66
PackLinuxI386sh::buildLoader(Filter const *ft)
67
0
{
68
0
    unsigned const sz_fold = sizeof(stub_i386_linux_elf_shell_fold);
69
0
    MemBuffer buf(sz_fold);
70
0
    memcpy(buf, stub_i386_linux_elf_shell_fold, sz_fold);
71
72
0
    checkPatch(nullptr, 0, 0, 0);  // reset
73
0
    patch_le32(buf,sz_fold,"UPX3",l_shname);
74
0
    patch_le32(buf,sz_fold,"UPX2",o_shname);
75
76
    // get fresh filter
77
0
    Filter fold_ft = *ft;
78
0
    fold_ft.init(ft->id, ft->addvalue);
79
0
    int preferred_ctos[2] = { ft->cto, -1 };
80
0
    fold_ft.preferred_ctos = preferred_ctos;
81
82
    // filter
83
0
    optimizeFilter(&fold_ft, buf, sz_fold);
84
0
    unsigned fold_hdrlen = sizeof(l_info) + sizeof(Elf32_Ehdr) +
85
0
        sizeof(Elf32_Phdr) * get_te16(&((Elf32_Ehdr const *)(void *)buf)->e_phnum);
86
0
    if (0 == get_le32(buf + fold_hdrlen)) {
87
        // inconsistent SIZEOF_HEADERS in *.lds (ld, binutils)
88
0
        fold_hdrlen = upx::umax(0x80u, fold_hdrlen);
89
0
    }
90
0
    bool success = fold_ft.filter(buf + fold_hdrlen, sz_fold - fold_hdrlen);
91
0
    UNUSED(success);
92
93
0
    buildLinuxLoader(
94
0
        stub_i386_linux_elf_shell_entry, sizeof(stub_i386_linux_elf_shell_entry),
95
0
        buf, sz_fold, ft );
96
0
}
97
98
0
void PackLinuxI386sh::patchLoader() { }
99
100
101
bool PackLinuxI386sh::getShellName(char *buf)
102
0
{
103
0
    exetype = -1;
104
0
    l_shname = (int) strcspn(buf, " \t\n\v\f\r");
105
0
    buf[l_shname] = 0;
106
0
    static char const *const shname[] = { // known shells that accept "-c" arg
107
0
        "ash", "bash", "bsh", "csh", "ksh", "pdksh", "sh", "tcsh", "zsh",
108
0
        "python", "python2", "python3",
109
0
        nullptr
110
0
    };
111
0
    const char *bname = strrchr(buf, '/');
112
0
    if (bname == nullptr)
113
0
        return false;
114
0
    for (int j = 0; nullptr != shname[j]; ++j) {
115
0
        if (0 == strcmp(shname[j], bname + 1)) {
116
0
            bool const s = bool(super::canPack());
117
0
            if (s) {
118
0
                opt->o_unix.blocksize = blocksize = file_size;
119
0
            }
120
0
            unsigned size = fi->st_size();
121
0
            if (size > (125<<10)) { // 128KB but allow 3KB for environment
122
0
                printWarn(fi->getName(), "Likely E2BIG for size=%u", size);
123
0
                return false;
124
0
            }
125
0
            return s;
126
0
        }
127
0
    }
128
0
    return false;
129
0
}
130
131
132
tribool PackLinuxI386sh::canPack()
133
0
{
134
0
#if defined(__linux__)  //{
135
    // only compress i386sh scripts when running under Linux
136
0
    char buf[512];
137
138
0
    fi->readx(buf, sizeof(buf));
139
0
    fi->seek(0, SEEK_SET);
140
0
    buf[sizeof(buf) - 1] = 0;
141
0
    if (!memcmp(buf, "#!/", 3)) {                       // #!/bin/sh
142
0
        o_shname = 2;
143
0
        return getShellName(&buf[o_shname]);
144
0
    }
145
0
    else if (!memcmp(buf, "#! /", 4)) {                 // #! /bin/sh
146
0
        o_shname = 3;
147
0
        return getShellName(&buf[o_shname]);
148
0
    }
149
0
#endif  //}
150
0
    return false;
151
0
}
152
153
154
void
155
PackLinuxI386sh::pack1(OutputFile *fo, Filter &)
156
0
{
157
0
    generateElfHdr(fo, stub_i386_linux_elf_shell_fold, 0x08048000);
158
0
}
159
160
off_t
161
PackLinuxI386sh::pack3(OutputFile *fo, Filter &ft)
162
0
{
163
0
    return elfout.phdr[0].p_filesz = super::pack3(fo,ft);
164
0
}
165
166
/* vim:set ts=4 sw=4 et: */