src: major cleanups, introduce new eXtended Span class
- initial minimally invasive eXtended Span implementation - rename ptr_diff to ptr_diff_bytes - move some files to util subdir - lots of cleanups - start using the new checked pointers - this needs some real-world testing
This commit is contained in:
parent
4318cc22ee
commit
c75d7a685d
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -311,18 +311,18 @@ jobs:
|
|||||||
@REM build UCL
|
@REM build UCL
|
||||||
cd %BDIR%\ucl
|
cd %BDIR%\ucl
|
||||||
set s=%H%\upx\vendor\ucl
|
set s=%H%\upx\vendor\ucl
|
||||||
cl -MT -O2 -W4 %DEFS% -I%s%\include -I%s% -c %s%\src\*.c
|
cl -MT -J -O2 -W4 %DEFS% -I%s%\include -I%s% -c %s%\src\*.c
|
||||||
link -lib -out:ucl.lib *.obj
|
link -lib -out:ucl.lib *.obj
|
||||||
@REM build zlib
|
@REM build zlib
|
||||||
cd %BDIR%\zlib
|
cd %BDIR%\zlib
|
||||||
cl -MT -O2 -W3 %DEFS% -c %H%\upx\vendor\zlib\*.c
|
cl -MT -J -O2 -W3 %DEFS% -c %H%\upx\vendor\zlib\*.c
|
||||||
link -lib -out:zlib.lib *.obj
|
link -lib -out:zlib.lib *.obj
|
||||||
@REM build UPX
|
@REM build UPX
|
||||||
cd %BDIR%\upx
|
cd %BDIR%\upx
|
||||||
set s=%H%\upx\src
|
set s=%H%\upx\src
|
||||||
cat .GITREV.txt
|
cat .GITREV.txt
|
||||||
set /p GITREV=<.GITREV.txt
|
set /p GITREV=<.GITREV.txt
|
||||||
cl -MT -EHsc -J -O2 -W4 -WX -DUPX_VERSION_GITREV="""%GITREV%""" %DEFS% -I%H%\upx\vendor\doctest -I%H%\upx\vendor\lzma-sdk -I%H%\upx\vendor\ucl\include -I%H%\upx\vendor\zlib -Feupx.exe %s%\*.cpp %BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib /link setargv.obj
|
cl -MT -EHsc -J -O2 -W4 -WX -DUPX_VERSION_GITREV="""%GITREV%""" %DEFS% -I%H%\upx\vendor\doctest -I%H%\upx\vendor\lzma-sdk -I%H%\upx\vendor\ucl\include -I%H%\upx\vendor\zlib -Feupx.exe %s%\*.cpp %s%\util\*.cpp %BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib /link setargv.obj
|
||||||
|
|
||||||
- name: 'Basic tests'
|
- name: 'Basic tests'
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|||||||
@ -83,7 +83,7 @@ list(SORT zlib_SOURCES)
|
|||||||
add_library(upx_vendor_zlib STATIC ${zlib_SOURCES})
|
add_library(upx_vendor_zlib STATIC ${zlib_SOURCES})
|
||||||
set_property(TARGET upx_vendor_zlib PROPERTY C_STANDARD 11)
|
set_property(TARGET upx_vendor_zlib PROPERTY C_STANDARD 11)
|
||||||
|
|
||||||
file(GLOB upx_SOURCES "src/*.cpp")
|
file(GLOB upx_SOURCES "src/*.cpp" "src/util/*.cpp")
|
||||||
list(SORT upx_SOURCES)
|
list(SORT upx_SOURCES)
|
||||||
add_executable(upx ${upx_SOURCES})
|
add_executable(upx ${upx_SOURCES})
|
||||||
set_property(TARGET upx PROPERTY CXX_STANDARD 14)
|
set_property(TARGET upx PROPERTY CXX_STANDARD 14)
|
||||||
@ -124,14 +124,14 @@ endif()
|
|||||||
set(t upx_vendor_ucl)
|
set(t upx_vendor_ucl)
|
||||||
target_include_directories(${t} PRIVATE vendor/ucl/include vendor/ucl)
|
target_include_directories(${t} PRIVATE vendor/ucl/include vendor/ucl)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(${t} PRIVATE -W4 ${warn_WX})
|
target_compile_options(${t} PRIVATE -J -W4 ${warn_WX})
|
||||||
else()
|
else()
|
||||||
target_compile_options(${t} PRIVATE -Wall -Wextra -Wvla ${warn_Werror})
|
target_compile_options(${t} PRIVATE -Wall -Wextra -Wvla ${warn_Werror})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(t upx_vendor_zlib)
|
set(t upx_vendor_zlib)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_VSNPRINTF -W3 ${warn_WX})
|
target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_VSNPRINTF -J -W3 ${warn_WX})
|
||||||
else()
|
else()
|
||||||
target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_UNISTD_H -DHAVE_VSNPRINTF)
|
target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_UNISTD_H -DHAVE_VSNPRINTF)
|
||||||
target_compile_options(${t} PRIVATE -Wall -Wextra -Wvla ${warn_Werror})
|
target_compile_options(${t} PRIVATE -Wall -Wextra -Wvla ${warn_Werror})
|
||||||
|
|||||||
11
src/Makefile
11
src/Makefile
@ -55,7 +55,7 @@ ALL_LDFLAGS = $(strip $(call all_flags,LDFLAGS))
|
|||||||
ALL_LDADD = $(strip $(call all_flags,LDADD))
|
ALL_LDADD = $(strip $(call all_flags,LDADD))
|
||||||
ALL_LIBS = $(strip $(call all_flags,LIBS))
|
ALL_LIBS = $(strip $(call all_flags,LIBS))
|
||||||
|
|
||||||
upx_SOURCES := $(sort $(wildcard $(srcdir)/*.cpp))
|
upx_SOURCES := $(sort $(wildcard $(srcdir)/*.cpp $(srcdir)/util/*.cpp))
|
||||||
upx_OBJECTS := $(notdir $(upx_SOURCES:.cpp=$(objext)))
|
upx_OBJECTS := $(notdir $(upx_SOURCES:.cpp=$(objext)))
|
||||||
|
|
||||||
ifneq ($(wildcard $(top_srcdir)/.git/.),)
|
ifneq ($(wildcard $(top_srcdir)/.git/.),)
|
||||||
@ -131,6 +131,8 @@ upx$(exeext): $(upx_OBJECTS) $(upx_DEPENDENCIES)
|
|||||||
|
|
||||||
%.o : %.cpp | ./.depend
|
%.o : %.cpp | ./.depend
|
||||||
$(strip $(CXX) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) -o $@ -c $<)
|
$(strip $(CXX) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) -o $@ -c $<)
|
||||||
|
%.o : util/%.cpp | ./.depend
|
||||||
|
$(strip $(CXX) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) -o $@ -c $<)
|
||||||
%.cpp.ii : %.cpp
|
%.cpp.ii : %.cpp
|
||||||
$(strip $(CXX) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) -o $@ -E $<)
|
$(strip $(CXX) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) -o $@ -E $<)
|
||||||
|
|
||||||
@ -207,13 +209,14 @@ endif
|
|||||||
# automatically format some C++ source code files
|
# automatically format some C++ source code files
|
||||||
ifeq ($(shell uname),Linux)
|
ifeq ($(shell uname),Linux)
|
||||||
CLANG_FORMAT_FILES += bele.h bele_policy.h
|
CLANG_FORMAT_FILES += bele.h bele_policy.h
|
||||||
CLANG_FORMAT_FILES += dt_check.cpp dt_impl.cpp except.cpp except.h
|
CLANG_FORMAT_FILES += except.cpp except.h
|
||||||
|
CLANG_FORMAT_FILES += file.cpp file.h
|
||||||
CLANG_FORMAT_FILES += linker.cpp linker.h packhead.cpp packmast.cpp packmast.h
|
CLANG_FORMAT_FILES += linker.cpp linker.h packhead.cpp packmast.cpp packmast.h
|
||||||
CLANG_FORMAT_FILES += main.cpp options.cpp options.h packer.cpp packer.h
|
CLANG_FORMAT_FILES += main.cpp options.cpp options.h packer.cpp packer.h
|
||||||
CLANG_FORMAT_FILES += p_tos.cpp p_tos.h
|
CLANG_FORMAT_FILES += p_tos.cpp p_tos.h
|
||||||
CLANG_FORMAT_FILES += s_djgpp2.cpp s_object.cpp s_vcsa.cpp s_win32.cpp screen.h
|
CLANG_FORMAT_FILES += s_djgpp2.cpp s_object.cpp s_vcsa.cpp s_win32.cpp screen.h
|
||||||
CLANG_FORMAT_FILES += snprintf.cpp
|
CLANG_FORMAT_FILES += ui.cpp ui.h work.cpp
|
||||||
CLANG_FORMAT_FILES += ui.cpp ui.h util.cpp util.h work.cpp
|
CLANG_FORMAT_FILES += $(wildcard util/[a-ln-z]*.[ch]* util/mem*.[ch]*)
|
||||||
clang-format:
|
clang-format:
|
||||||
$(top_srcdir)/misc/scripts/upx-clang-format -i $(addprefix $(top_srcdir)/src/,$(sort $(CLANG_FORMAT_FILES)))
|
$(top_srcdir)/misc/scripts/upx-clang-format -i $(addprefix $(top_srcdir)/src/,$(sort $(CLANG_FORMAT_FILES)))
|
||||||
.PHONY: clang-format
|
.PHONY: clang-format
|
||||||
|
|||||||
81
src/bele.h
81
src/bele.h
@ -25,8 +25,9 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UPX_BELE_H
|
#pragma once
|
||||||
#define __UPX_BELE_H 1
|
#ifndef UPX_BELE_H__
|
||||||
|
#define UPX_BELE_H__ 1
|
||||||
|
|
||||||
// BE - Big Endian
|
// BE - Big Endian
|
||||||
// LE - Little Endian
|
// LE - Little Endian
|
||||||
@ -294,6 +295,8 @@ struct alignas(1) BE16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const { return get_be16(d); }
|
operator unsigned() const { return get_be16(d); }
|
||||||
|
|
||||||
|
bool operator<(const BE16 &v) const { return unsigned(*this) < unsigned(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) BE32 {
|
struct alignas(1) BE32 {
|
||||||
@ -341,6 +344,8 @@ struct alignas(1) BE32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const { return get_be32(d); }
|
operator unsigned() const { return get_be32(d); }
|
||||||
|
|
||||||
|
bool operator<(const BE32 &v) const { return unsigned(*this) < unsigned(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) BE64 {
|
struct alignas(1) BE64 {
|
||||||
@ -388,6 +393,8 @@ struct alignas(1) BE64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator upx_uint64_t() const { return get_be64(d); }
|
operator upx_uint64_t() const { return get_be64(d); }
|
||||||
|
|
||||||
|
bool operator<(const BE64 &v) const { return upx_uint64_t(*this) < upx_uint64_t(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) LE16 {
|
struct alignas(1) LE16 {
|
||||||
@ -435,6 +442,8 @@ struct alignas(1) LE16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const { return get_le16(d); }
|
operator unsigned() const { return get_le16(d); }
|
||||||
|
|
||||||
|
bool operator<(const LE16 &v) const { return unsigned(*this) < unsigned(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) LE32 {
|
struct alignas(1) LE32 {
|
||||||
@ -482,6 +491,8 @@ struct alignas(1) LE32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const { return get_le32(d); }
|
operator unsigned() const { return get_le32(d); }
|
||||||
|
|
||||||
|
bool operator<(const LE32 &v) const { return unsigned(*this) < unsigned(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) LE64 {
|
struct alignas(1) LE64 {
|
||||||
@ -529,6 +540,8 @@ struct alignas(1) LE64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator upx_uint64_t() const { return get_le64(d); }
|
operator upx_uint64_t() const { return get_le64(d); }
|
||||||
|
|
||||||
|
bool operator<(const LE64 &v) const { return upx_uint64_t(*this) < upx_uint64_t(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// native types
|
// native types
|
||||||
@ -548,20 +561,20 @@ typedef LE64 NE64;
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator+(T *ptr, const BE16 &v) {
|
inline T *operator+(T *ptr, const BE16 &v) {
|
||||||
return ptr + (unsigned) v;
|
return ptr + unsigned(v);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator-(T *ptr, const BE16 &v) {
|
inline T *operator-(T *ptr, const BE16 &v) {
|
||||||
return ptr - (unsigned) v;
|
return ptr - unsigned(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator+(T *ptr, const BE32 &v) {
|
inline T *operator+(T *ptr, const BE32 &v) {
|
||||||
return ptr + (unsigned) v;
|
return ptr + unsigned(v);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator-(T *ptr, const BE32 &v) {
|
inline T *operator-(T *ptr, const BE32 &v) {
|
||||||
return ptr - (unsigned) v;
|
return ptr - unsigned(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are not implemented on purpose and will cause link-time errors
|
// these are not implemented on purpose and will cause link-time errors
|
||||||
@ -572,20 +585,20 @@ T *operator-(T *ptr, const BE64 &v);
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator+(T *ptr, const LE16 &v) {
|
inline T *operator+(T *ptr, const LE16 &v) {
|
||||||
return ptr + (unsigned) v;
|
return ptr + unsigned(v);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator-(T *ptr, const LE16 &v) {
|
inline T *operator-(T *ptr, const LE16 &v) {
|
||||||
return ptr - (unsigned) v;
|
return ptr - unsigned(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator+(T *ptr, const LE32 &v) {
|
inline T *operator+(T *ptr, const LE32 &v) {
|
||||||
return ptr + (unsigned) v;
|
return ptr + unsigned(v);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T *operator-(T *ptr, const LE32 &v) {
|
inline T *operator-(T *ptr, const LE32 &v) {
|
||||||
return ptr - (unsigned) v;
|
return ptr - unsigned(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are not implemented on purpose and will cause link-time errors
|
// these are not implemented on purpose and will cause link-time errors
|
||||||
@ -598,35 +611,35 @@ T *operator-(T *ptr, const LE64 &v);
|
|||||||
// global overloads
|
// global overloads
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
inline unsigned ALIGN_DOWN(unsigned a, const BE32 &b) { return ALIGN_DOWN(a, (unsigned) b); }
|
inline unsigned ALIGN_DOWN(unsigned a, const BE32 &b) { return ALIGN_DOWN(a, unsigned(b)); }
|
||||||
inline unsigned ALIGN_DOWN(const BE32 &a, unsigned b) { return ALIGN_DOWN((unsigned) a, b); }
|
inline unsigned ALIGN_DOWN(const BE32 &a, unsigned b) { return ALIGN_DOWN(unsigned(a), b); }
|
||||||
inline unsigned ALIGN_UP(unsigned a, const BE32 &b) { return ALIGN_UP(a, (unsigned) b); }
|
inline unsigned ALIGN_UP(unsigned a, const BE32 &b) { return ALIGN_UP(a, unsigned(b)); }
|
||||||
inline unsigned ALIGN_UP(const BE32 &a, unsigned b) { return ALIGN_UP((unsigned) a, b); }
|
inline unsigned ALIGN_UP(const BE32 &a, unsigned b) { return ALIGN_UP(unsigned(a), b); }
|
||||||
|
|
||||||
inline unsigned ALIGN_DOWN(unsigned a, const LE32 &b) { return ALIGN_DOWN(a, (unsigned) b); }
|
inline unsigned ALIGN_DOWN(unsigned a, const LE32 &b) { return ALIGN_DOWN(a, unsigned(b)); }
|
||||||
inline unsigned ALIGN_DOWN(const LE32 &a, unsigned b) { return ALIGN_DOWN((unsigned) a, b); }
|
inline unsigned ALIGN_DOWN(const LE32 &a, unsigned b) { return ALIGN_DOWN(unsigned(a), b); }
|
||||||
inline unsigned ALIGN_UP(unsigned a, const LE32 &b) { return ALIGN_UP(a, (unsigned) b); }
|
inline unsigned ALIGN_UP(unsigned a, const LE32 &b) { return ALIGN_UP(a, unsigned(b)); }
|
||||||
inline unsigned ALIGN_UP(const LE32 &a, unsigned b) { return ALIGN_UP((unsigned) a, b); }
|
inline unsigned ALIGN_UP(const LE32 &a, unsigned b) { return ALIGN_UP(unsigned(a), b); }
|
||||||
|
|
||||||
inline unsigned UPX_MAX(unsigned a, const BE16 &b) { return UPX_MAX(a, (unsigned) b); }
|
inline unsigned UPX_MAX(unsigned a, const BE16 &b) { return UPX_MAX(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MAX(const BE16 &a, unsigned b) { return UPX_MAX((unsigned) a, b); }
|
inline unsigned UPX_MAX(const BE16 &a, unsigned b) { return UPX_MAX(unsigned(a), b); }
|
||||||
inline unsigned UPX_MIN(unsigned a, const BE16 &b) { return UPX_MIN(a, (unsigned) b); }
|
inline unsigned UPX_MIN(unsigned a, const BE16 &b) { return UPX_MIN(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MIN(const BE16 &a, unsigned b) { return UPX_MIN((unsigned) a, b); }
|
inline unsigned UPX_MIN(const BE16 &a, unsigned b) { return UPX_MIN(unsigned(a), b); }
|
||||||
|
|
||||||
inline unsigned UPX_MAX(unsigned a, const BE32 &b) { return UPX_MAX(a, (unsigned) b); }
|
inline unsigned UPX_MAX(unsigned a, const BE32 &b) { return UPX_MAX(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MAX(const BE32 &a, unsigned b) { return UPX_MAX((unsigned) a, b); }
|
inline unsigned UPX_MAX(const BE32 &a, unsigned b) { return UPX_MAX(unsigned(a), b); }
|
||||||
inline unsigned UPX_MIN(unsigned a, const BE32 &b) { return UPX_MIN(a, (unsigned) b); }
|
inline unsigned UPX_MIN(unsigned a, const BE32 &b) { return UPX_MIN(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MIN(const BE32 &a, unsigned b) { return UPX_MIN((unsigned) a, b); }
|
inline unsigned UPX_MIN(const BE32 &a, unsigned b) { return UPX_MIN(unsigned(a), b); }
|
||||||
|
|
||||||
inline unsigned UPX_MAX(unsigned a, const LE16 &b) { return UPX_MAX(a, (unsigned) b); }
|
inline unsigned UPX_MAX(unsigned a, const LE16 &b) { return UPX_MAX(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MAX(const LE16 &a, unsigned b) { return UPX_MAX((unsigned) a, b); }
|
inline unsigned UPX_MAX(const LE16 &a, unsigned b) { return UPX_MAX(unsigned(a), b); }
|
||||||
inline unsigned UPX_MIN(unsigned a, const LE16 &b) { return UPX_MIN(a, (unsigned) b); }
|
inline unsigned UPX_MIN(unsigned a, const LE16 &b) { return UPX_MIN(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MIN(const LE16 &a, unsigned b) { return UPX_MIN((unsigned) a, b); }
|
inline unsigned UPX_MIN(const LE16 &a, unsigned b) { return UPX_MIN(unsigned(a), b); }
|
||||||
|
|
||||||
inline unsigned UPX_MAX(unsigned a, const LE32 &b) { return UPX_MAX(a, (unsigned) b); }
|
inline unsigned UPX_MAX(unsigned a, const LE32 &b) { return UPX_MAX(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MAX(const LE32 &a, unsigned b) { return UPX_MAX((unsigned) a, b); }
|
inline unsigned UPX_MAX(const LE32 &a, unsigned b) { return UPX_MAX(unsigned(a), b); }
|
||||||
inline unsigned UPX_MIN(unsigned a, const LE32 &b) { return UPX_MIN(a, (unsigned) b); }
|
inline unsigned UPX_MIN(unsigned a, const LE32 &b) { return UPX_MIN(a, unsigned(b)); }
|
||||||
inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN((unsigned) a, b); }
|
inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a), b); }
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// misc support
|
// misc support
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UPX_BELE_H
|
#ifndef UPX_BELE_H__
|
||||||
#error "this is an internal include file"
|
#error "this is an internal include file"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
106
src/bptr.h
106
src/bptr.h
@ -1,106 +0,0 @@
|
|||||||
/* bptr.h --
|
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
|
||||||
|
|
||||||
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
|
||||||
Copyright (C) 1996-2022 Laszlo Molnar
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
|
||||||
and/or modify them under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; see the file COPYING.
|
|
||||||
If not, write to the Free Software Foundation, Inc.,
|
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
|
||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __UPX_BPTR_H
|
|
||||||
#define __UPX_BPTR_H 1
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// BoundedPtr
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class BoundedPtr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//typedef T* StoredType;
|
|
||||||
//typedef T* PointerType;
|
|
||||||
//typedef T& ReferenceType;
|
|
||||||
|
|
||||||
~BoundedPtr() { }
|
|
||||||
|
|
||||||
BoundedPtr(void* base, size_t size_in_bytes, T* ptr=nullptr)
|
|
||||||
: ptr_(ptr), base_(base), size_in_bytes_(0)
|
|
||||||
{
|
|
||||||
assert(base_ != nullptr);
|
|
||||||
size_in_bytes_ = mem_size(1, size_in_bytes);
|
|
||||||
check();
|
|
||||||
}
|
|
||||||
|
|
||||||
// assignment
|
|
||||||
BoundedPtr& operator= (const BoundedPtr& other) {
|
|
||||||
assert(base_ == other.base_);
|
|
||||||
assert(size_in_bytes_ == other.size_in_bytes_);
|
|
||||||
ptr_ = other.ptr_; check(); return *this;
|
|
||||||
}
|
|
||||||
BoundedPtr& operator= (T* other) {
|
|
||||||
ptr_ = other; check(); return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator T* () { return ptr_; }
|
|
||||||
operator const T* () const { return ptr_; }
|
|
||||||
|
|
||||||
BoundedPtr& operator += (size_t n) {
|
|
||||||
checkNULL(); ptr_ += n; checkRange(); return *this;
|
|
||||||
}
|
|
||||||
BoundedPtr& operator -= (size_t n) {
|
|
||||||
checkNULL(); ptr_ -= n; checkRange(); return *this;
|
|
||||||
}
|
|
||||||
BoundedPtr& operator ++ (void) {
|
|
||||||
checkNULL(); ptr_ += 1; checkRange(); return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void checkNULL() const {
|
|
||||||
if __acc_very_unlikely(!ptr_)
|
|
||||||
throwCantUnpack("unexpected NULL pointer; take care!");
|
|
||||||
}
|
|
||||||
void checkRange() const {
|
|
||||||
size_t off = (const char *) ptr_ - (const char *) base_;
|
|
||||||
if __acc_very_unlikely(off > size_in_bytes_)
|
|
||||||
throwCantUnpack("pointer out of range; take care!");
|
|
||||||
}
|
|
||||||
void check() const { // check ptr_ invariant: either NULL or valid checkRange()
|
|
||||||
if (ptr_ != nullptr)
|
|
||||||
checkRange();
|
|
||||||
}
|
|
||||||
|
|
||||||
T* ptr_;
|
|
||||||
void* base_;
|
|
||||||
size_t size_in_bytes_;
|
|
||||||
|
|
||||||
// disable copy
|
|
||||||
BoundedPtr(const BoundedPtr&) = delete;
|
|
||||||
// disable dynamic allocation
|
|
||||||
ACC_CXX_DISABLE_NEW_DELETE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
|
||||||
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "compress.h"
|
#include "compress.h"
|
||||||
#include "mem.h"
|
#include "util/membuffer.h"
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "compress.h"
|
#include "compress.h"
|
||||||
#include "mem.h"
|
#include "util/membuffer.h"
|
||||||
|
|
||||||
#if (ACC_CC_CLANG)
|
#if (ACC_CC_CLANG)
|
||||||
# pragma clang diagnostic ignored "-Wshadow"
|
# pragma clang diagnostic ignored "-Wshadow"
|
||||||
|
|||||||
@ -291,7 +291,7 @@ unsigned upx_ucl_crc32(const void *buf, unsigned len, unsigned crc)
|
|||||||
|
|
||||||
#if DEBUG && 1
|
#if DEBUG && 1
|
||||||
|
|
||||||
#include "mem.h"
|
#include "util/membuffer.h"
|
||||||
|
|
||||||
static bool check_ucl(const int method, const unsigned expected_c_len) {
|
static bool check_ucl(const int method, const unsigned expected_c_len) {
|
||||||
const unsigned u_len = 16384;
|
const unsigned u_len = 16384;
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "compress.h"
|
#include "compress.h"
|
||||||
#include "mem.h"
|
#include "util/membuffer.h"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
57
src/conf.h
57
src/conf.h
@ -25,9 +25,9 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __UPX_CONF_H
|
#ifndef UPX_CONF_H__
|
||||||
#define __UPX_CONF_H 1
|
#define UPX_CONF_H__ 1
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
# if (__cplusplus >= 201402L)
|
# if (__cplusplus >= 201402L)
|
||||||
@ -356,7 +356,7 @@ template <class T>
|
|||||||
inline const T& UPX_MIN(const T& a, const T& b) { if (a < b) return a; return b; }
|
inline const T& UPX_MIN(const T& a, const T& b) { if (a < b) return a; return b; }
|
||||||
|
|
||||||
|
|
||||||
// An Array allocates memory on the heap, but automatically
|
// An Array allocates memory on the heap, and automatically
|
||||||
// gets destructed when leaving scope or on exceptions.
|
// gets destructed when leaving scope or on exceptions.
|
||||||
#define Array(type, var, size) \
|
#define Array(type, var, size) \
|
||||||
MemBuffer var ## _membuf(mem_size(sizeof(type), size)); \
|
MemBuffer var ## _membuf(mem_size(sizeof(type), size)); \
|
||||||
@ -397,6 +397,23 @@ constexpr bool string_ge(const char *a, const char *b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// raw_bytes() - get underlying memory from checked buffers/pointers.
|
||||||
|
// This is overloaded by various utility classes like BoundedPtr,
|
||||||
|
// MemBuffer and Span.
|
||||||
|
//
|
||||||
|
// Note that the pointer type is retained, the "_bytes" hints size_in_bytes
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// default: for any regular pointer, raw_bytes() is just the pointer itself
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(T *ptr, size_t size_in_bytes) {
|
||||||
|
if (size_in_bytes > 0) {
|
||||||
|
assert(ptr != nullptr);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// constants
|
// constants
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@ -712,7 +729,7 @@ struct upx_compress_result_t
|
|||||||
// globals
|
// globals
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "snprintf.h" // must get included first!
|
#include "util/snprintf.h" // must get included first!
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <new>
|
#include <new>
|
||||||
@ -722,19 +739,27 @@ struct upx_compress_result_t
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "except.h"
|
#include "except.h"
|
||||||
#include "bele.h"
|
#include "bele.h"
|
||||||
#include "util.h"
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
#include "util/util.h"
|
||||||
//#define DOCTEST_CONFIG_DISABLE
|
|
||||||
#include <doctest/parts/doctest_fwd.h>
|
|
||||||
|
|
||||||
// classes
|
// classes
|
||||||
class ElfLinker;
|
class ElfLinker;
|
||||||
typedef ElfLinker Linker;
|
typedef ElfLinker Linker;
|
||||||
|
|
||||||
// dt_check.cpp
|
// util/membuffer.h
|
||||||
void upx_compiler_sanity_check(void);
|
class MemBuffer;
|
||||||
bool upx_doctest_check(void);
|
void *membuffer_get_void_ptr(MemBuffer &mb);
|
||||||
|
unsigned membuffer_get_size(MemBuffer &mb);
|
||||||
|
|
||||||
|
#include "util/xspan.h"
|
||||||
|
|
||||||
|
//#define DOCTEST_CONFIG_DISABLE
|
||||||
|
#include <doctest/parts/doctest_fwd.h>
|
||||||
|
|
||||||
|
// util/dt_check.cpp
|
||||||
|
void upx_compiler_sanity_check();
|
||||||
|
bool upx_doctest_check();
|
||||||
|
bool upx_doctest_check(int argc, char **argv);
|
||||||
|
|
||||||
// main.cpp
|
// main.cpp
|
||||||
extern const char *progname;
|
extern const char *progname;
|
||||||
@ -754,7 +779,7 @@ void printWarn(const char *iname, const char *format, ...) attribute_format(2, 3
|
|||||||
void infoWarning(const char *format, ...) attribute_format(1, 2);
|
void infoWarning(const char *format, ...) attribute_format(1, 2);
|
||||||
void infoHeader(const char *format, ...) attribute_format(1, 2);
|
void infoHeader(const char *format, ...) attribute_format(1, 2);
|
||||||
void info(const char *format, ...) attribute_format(1, 2);
|
void info(const char *format, ...) attribute_format(1, 2);
|
||||||
void infoHeader(void);
|
void infoHeader();
|
||||||
void infoWriting(const char *what, long size);
|
void infoWriting(const char *what, long size);
|
||||||
|
|
||||||
// work.cpp
|
// work.cpp
|
||||||
@ -763,10 +788,10 @@ int do_files(int i, int argc, char *argv[]);
|
|||||||
|
|
||||||
// help.cpp
|
// help.cpp
|
||||||
extern const char gitrev[];
|
extern const char gitrev[];
|
||||||
void show_head(void);
|
void show_head();
|
||||||
void show_help(int verbose=0);
|
void show_help(int verbose=0);
|
||||||
void show_license(void);
|
void show_license();
|
||||||
void show_usage(void);
|
void show_usage();
|
||||||
void show_version(int);
|
void show_version(int);
|
||||||
|
|
||||||
// compress.cpp
|
// compress.cpp
|
||||||
|
|||||||
51
src/except.h
51
src/except.h
@ -25,8 +25,9 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UPX_EXCEPT_H
|
#pragma once
|
||||||
#define __UPX_EXCEPT_H 1
|
#ifndef UPX_EXCEPT_H__
|
||||||
|
#define UPX_EXCEPT_H__ 1
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
@ -50,16 +51,16 @@ public:
|
|||||||
bool isWarning() const noexcept { return is_warning; }
|
bool isWarning() const noexcept { return is_warning; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *msg;
|
char *msg = nullptr;
|
||||||
int err;
|
int err = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool is_warning; // can be set by subclasses
|
bool is_warning = false; // can be set by subclasses
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// disable assignment
|
// disable assignment
|
||||||
Throwable &operator=(const Throwable &);
|
Throwable &operator=(const Throwable &) = delete;
|
||||||
// disable dynamic allocation
|
// disable dynamic allocation => force throwing by value
|
||||||
ACC_CXX_DISABLE_NEW_DELETE
|
ACC_CXX_DISABLE_NEW_DELETE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -192,27 +193,27 @@ public:
|
|||||||
|
|
||||||
#undef NORET
|
#undef NORET
|
||||||
#if 1 && defined(__GNUC__)
|
#if 1 && defined(__GNUC__)
|
||||||
#define NORET __attribute__((__noreturn__))
|
#define NORET __attribute__((__noreturn__)) __acc_noinline
|
||||||
#else
|
#else
|
||||||
#define NORET /*empty*/
|
#define NORET __acc_noinline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void throwCantPack(const char *msg) NORET;
|
NORET void throwCantPack(const char *msg);
|
||||||
void throwCantPackExact() NORET;
|
NORET void throwCantPackExact();
|
||||||
void throwUnknownExecutableFormat(const char *msg = nullptr, bool warn = false) NORET;
|
NORET void throwUnknownExecutableFormat(const char *msg = nullptr, bool warn = false);
|
||||||
void throwNotCompressible(const char *msg = nullptr) NORET;
|
NORET void throwNotCompressible(const char *msg = nullptr);
|
||||||
void throwAlreadyPacked(const char *msg = nullptr) NORET;
|
NORET void throwAlreadyPacked(const char *msg = nullptr);
|
||||||
void throwAlreadyPackedByUPX(const char *msg = nullptr) NORET;
|
NORET void throwAlreadyPackedByUPX(const char *msg = nullptr);
|
||||||
void throwCantUnpack(const char *msg) NORET;
|
NORET void throwCantUnpack(const char *msg);
|
||||||
void throwNotPacked(const char *msg = nullptr) NORET;
|
NORET void throwNotPacked(const char *msg = nullptr);
|
||||||
void throwFilterException() NORET;
|
NORET void throwFilterException();
|
||||||
void throwBadLoader() NORET;
|
NORET void throwBadLoader();
|
||||||
void throwChecksumError() NORET;
|
NORET void throwChecksumError();
|
||||||
void throwCompressedDataViolation() NORET;
|
NORET void throwCompressedDataViolation();
|
||||||
void throwInternalError(const char *msg) NORET;
|
NORET void throwInternalError(const char *msg);
|
||||||
void throwOutOfMemoryException(const char *msg = nullptr) NORET;
|
NORET void throwOutOfMemoryException(const char *msg = nullptr);
|
||||||
void throwIOException(const char *msg = nullptr, int e = 0) NORET;
|
NORET void throwIOException(const char *msg = nullptr, int e = 0);
|
||||||
void throwEOFException(const char *msg = nullptr, int e = 0) NORET;
|
NORET void throwEOFException(const char *msg = nullptr, int e = 0);
|
||||||
|
|
||||||
#undef NORET
|
#undef NORET
|
||||||
|
|
||||||
|
|||||||
334
src/file.cpp
334
src/file.cpp
@ -25,59 +25,48 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "mem.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// static functions
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void File::chmod(const char *name, int mode)
|
void FileBase::chmod(const char *name, int mode) {
|
||||||
{
|
|
||||||
#if (HAVE_CHMOD)
|
#if (HAVE_CHMOD)
|
||||||
if (::chmod(name,mode) != 0)
|
if (::chmod(name, mode) != 0)
|
||||||
throwIOException(name,errno);
|
throwIOException(name, errno);
|
||||||
#else
|
#else
|
||||||
UNUSED(name); UNUSED(mode);
|
UNUSED(name);
|
||||||
|
UNUSED(mode);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileBase::rename(const char *old_, const char *new_) {
|
||||||
void File::rename(const char *old_, const char *new_)
|
|
||||||
{
|
|
||||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||||
if (::_rename(old_,new_) != 0)
|
if (::_rename(old_, new_) != 0)
|
||||||
#else
|
#else
|
||||||
if (::rename(old_,new_) != 0)
|
if (::rename(old_, new_) != 0)
|
||||||
#endif
|
#endif
|
||||||
throwIOException("rename error",errno);
|
throwIOException("rename error", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileBase::unlink(const char *name) {
|
||||||
void File::unlink(const char *name)
|
|
||||||
{
|
|
||||||
if (::unlink(name) != 0)
|
if (::unlink(name) != 0)
|
||||||
throwIOException(name,errno);
|
throwIOException(name, errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
FileBase::FileBase() :
|
FileBase::FileBase()
|
||||||
_fd(-1), _flags(0), _shflags(0), _mode(0), _name(nullptr), _offset(0), _length(0)
|
: _fd(-1), _flags(0), _shflags(0), _mode(0), _name(nullptr), _offset(0), _length(0) {
|
||||||
{
|
memset(&st, 0, sizeof(st));
|
||||||
memset(&st,0,sizeof(st));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileBase::~FileBase() {
|
||||||
FileBase::~FileBase()
|
#if 0 && defined(__GNUC__) // debug
|
||||||
{
|
|
||||||
#if 0 && defined(__GNUC__) // debug
|
|
||||||
if (isOpen())
|
if (isOpen())
|
||||||
fprintf(stderr,"%s: %s\n", _name, __PRETTY_FUNCTION__);
|
fprintf(stderr,"%s: %s\n", _name, __PRETTY_FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
@ -87,17 +76,14 @@ FileBase::~FileBase()
|
|||||||
closex();
|
closex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileBase::do_sopen() {
|
||||||
bool FileBase::do_sopen()
|
|
||||||
{
|
|
||||||
if (_shflags < 0)
|
if (_shflags < 0)
|
||||||
_fd = ::open(_name, _flags, _mode);
|
_fd = ::open(_name, _flags, _mode);
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||||
_fd = ::open(_name,_flags | _shflags, _mode);
|
_fd = ::open(_name, _flags | _shflags, _mode);
|
||||||
#elif defined(__MINT__)
|
#elif defined(__MINT__)
|
||||||
_fd = ::open(_name,_flags | (_shflags & O_SHMODE), _mode);
|
_fd = ::open(_name, _flags | (_shflags & O_SHMODE), _mode);
|
||||||
#elif defined(SH_DENYRW)
|
#elif defined(SH_DENYRW)
|
||||||
_fd = ::sopen(_name, _flags, _shflags, _mode);
|
_fd = ::sopen(_name, _flags, _shflags, _mode);
|
||||||
#else
|
#else
|
||||||
@ -112,9 +98,7 @@ bool FileBase::do_sopen()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileBase::close() {
|
||||||
bool FileBase::close()
|
|
||||||
{
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
if (isOpen() && _fd != STDIN_FILENO && _fd != STDOUT_FILENO && _fd != STDERR_FILENO)
|
if (isOpen() && _fd != STDIN_FILENO && _fd != STDOUT_FILENO && _fd != STDERR_FILENO)
|
||||||
if (::close(_fd) == -1)
|
if (::close(_fd) == -1)
|
||||||
@ -128,53 +112,15 @@ bool FileBase::close()
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileBase::closex() {
|
||||||
void FileBase::closex()
|
|
||||||
{
|
|
||||||
if (!close())
|
if (!close())
|
||||||
throwIOException("close failed",errno);
|
throwIOException("close failed", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upx_off_t FileBase::seek(upx_off_t off, int whence) {
|
||||||
int FileBase::read(void *buf, int len)
|
|
||||||
{
|
|
||||||
if (!isOpen() || len < 0)
|
|
||||||
throwIOException("bad read");
|
|
||||||
mem_size_assert(1, len); // sanity check
|
|
||||||
errno = 0;
|
|
||||||
long l = acc_safe_hread(_fd, buf, len);
|
|
||||||
if (errno)
|
|
||||||
throwIOException("read error",errno);
|
|
||||||
return (int) l;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int FileBase::readx(void *buf, int len)
|
|
||||||
{
|
|
||||||
int l = this->read(buf, len);
|
|
||||||
if (l != len)
|
|
||||||
throwEOFException();
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FileBase::write(const void *buf, int len)
|
|
||||||
{
|
|
||||||
if (!isOpen() || len < 0)
|
|
||||||
throwIOException("bad write");
|
|
||||||
mem_size_assert(1, len); // sanity check
|
|
||||||
errno = 0;
|
|
||||||
long l = acc_safe_hwrite(_fd, buf, len);
|
|
||||||
if (l != len)
|
|
||||||
throwIOException("write error",errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
upx_off_t FileBase::seek(upx_off_t off, int whence)
|
|
||||||
{
|
|
||||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
|
||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
throwIOException("bad seek 1");
|
throwIOException("bad seek 1");
|
||||||
|
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||||
if (whence == SEEK_SET) {
|
if (whence == SEEK_SET) {
|
||||||
if (off < 0)
|
if (off < 0)
|
||||||
throwIOException("bad seek 2");
|
throwIOException("bad seek 2");
|
||||||
@ -186,51 +132,34 @@ upx_off_t FileBase::seek(upx_off_t off, int whence)
|
|||||||
off += _offset + _length;
|
off += _offset + _length;
|
||||||
whence = SEEK_SET;
|
whence = SEEK_SET;
|
||||||
}
|
}
|
||||||
if (::lseek(_fd,off,whence) < 0)
|
if (::lseek(_fd, off, whence) < 0)
|
||||||
throwIOException("seek error",errno);
|
throwIOException("seek error", errno);
|
||||||
return off - _offset;
|
return off - _offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upx_off_t FileBase::tell() const {
|
||||||
upx_off_t FileBase::tell() const
|
|
||||||
{
|
|
||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
throwIOException("bad tell");
|
throwIOException("bad tell");
|
||||||
upx_off_t l = ::lseek(_fd, 0, SEEK_CUR);
|
upx_off_t l = ::lseek(_fd, 0, SEEK_CUR);
|
||||||
if (l < 0)
|
if (l < 0)
|
||||||
throwIOException("tell error",errno);
|
throwIOException("tell error", errno);
|
||||||
return l - _offset;
|
return l - _offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileBase::set_extent(upx_off_t offset, upx_off_t length) {
|
||||||
void FileBase::set_extent(upx_off_t offset, upx_off_t length)
|
|
||||||
{
|
|
||||||
_offset = offset;
|
_offset = offset;
|
||||||
_length = length;
|
_length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_off_t FileBase::st_size() const
|
upx_off_t FileBase::st_size() const { return _length; }
|
||||||
{
|
|
||||||
return _length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
InputFile::InputFile()
|
InputFile::InputFile() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void InputFile::sopen(const char *name, int flags, int shflags) {
|
||||||
InputFile::~InputFile()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InputFile::sopen(const char *name, int flags, int shflags)
|
|
||||||
{
|
|
||||||
close();
|
close();
|
||||||
_name = name;
|
_name = name;
|
||||||
_flags = flags;
|
_flags = flags;
|
||||||
@ -238,8 +167,7 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
|||||||
_mode = 0;
|
_mode = 0;
|
||||||
_offset = 0;
|
_offset = 0;
|
||||||
_length = 0;
|
_length = 0;
|
||||||
if (!FileBase::do_sopen())
|
if (!super::do_sopen()) {
|
||||||
{
|
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
throw FileNotFoundException(_name, errno);
|
throw FileNotFoundException(_name, errno);
|
||||||
else if (errno == EEXIST)
|
else if (errno == EEXIST)
|
||||||
@ -250,80 +178,40 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
|||||||
_length_orig = _length;
|
_length_orig = _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int InputFile::read(SPAN_P(void) buf, int len) {
|
||||||
int InputFile::read(void *buf, int len)
|
if (!isOpen() || len < 0)
|
||||||
{
|
throwIOException("bad read");
|
||||||
return super::read(buf, len);
|
mem_size_assert(1, len); // sanity check
|
||||||
|
errno = 0;
|
||||||
|
long l = acc_safe_hread(_fd, raw_bytes(buf, len), len);
|
||||||
|
if (errno)
|
||||||
|
throwIOException("read error", errno);
|
||||||
|
return (int) l;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InputFile::readx(void *buf, int len)
|
int InputFile::readx(SPAN_P(void) buf, int len) {
|
||||||
{
|
int l = this->read(buf, len);
|
||||||
return super::readx(buf, len);
|
if (l != len)
|
||||||
|
throwEOFException();
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upx_off_t InputFile::seek(upx_off_t off, int whence) {
|
||||||
int InputFile::read(MemBuffer *buf, int len)
|
|
||||||
{
|
|
||||||
buf->checkState();
|
|
||||||
assert((unsigned)len <= buf->getSize());
|
|
||||||
return read(buf->getVoidPtr(), len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int InputFile::readx(MemBuffer *buf, int len)
|
|
||||||
{
|
|
||||||
buf->checkState();
|
|
||||||
assert((unsigned)len <= buf->getSize());
|
|
||||||
return read(buf->getVoidPtr(), len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int InputFile::read(MemBuffer &buf, int len)
|
|
||||||
{
|
|
||||||
return read(&buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int InputFile::readx(MemBuffer &buf, int len)
|
|
||||||
{
|
|
||||||
return readx(&buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
upx_off_t InputFile::seek(upx_off_t off, int whence)
|
|
||||||
{
|
|
||||||
upx_off_t pos = super::seek(off, whence);
|
upx_off_t pos = super::seek(off, whence);
|
||||||
if (_length < pos)
|
if (_length < pos)
|
||||||
throwIOException("bad seek 4");
|
throwIOException("bad seek 4");
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upx_off_t InputFile::st_size_orig() const { return _length_orig; }
|
||||||
upx_off_t InputFile::tell() const
|
|
||||||
{
|
|
||||||
return super::tell();
|
|
||||||
}
|
|
||||||
|
|
||||||
upx_off_t InputFile::st_size_orig() const
|
|
||||||
{
|
|
||||||
return _length_orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
OutputFile::OutputFile() :
|
OutputFile::OutputFile() : bytes_written(0) {}
|
||||||
bytes_written(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void OutputFile::sopen(const char *name, int flags, int shflags, int mode) {
|
||||||
OutputFile::~OutputFile()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
|
||||||
{
|
|
||||||
close();
|
close();
|
||||||
_name = name;
|
_name = name;
|
||||||
_flags = flags;
|
_flags = flags;
|
||||||
@ -331,8 +219,7 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
|||||||
_mode = mode;
|
_mode = mode;
|
||||||
_offset = 0;
|
_offset = 0;
|
||||||
_length = 0;
|
_length = 0;
|
||||||
if (!FileBase::do_sopen())
|
if (!super::do_sopen()) {
|
||||||
{
|
|
||||||
#if 0
|
#if 0
|
||||||
// don't throw FileNotFound here -- this is confusing
|
// don't throw FileNotFound here -- this is confusing
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
@ -340,15 +227,13 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (errno == EEXIST)
|
if (errno == EEXIST)
|
||||||
throw FileAlreadyExistsException(_name,errno);
|
throw FileAlreadyExistsException(_name, errno);
|
||||||
else
|
else
|
||||||
throwIOException(_name,errno);
|
throwIOException(_name, errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OutputFile::openStdout(int flags, bool force) {
|
||||||
bool OutputFile::openStdout(int flags, bool force)
|
|
||||||
{
|
|
||||||
close();
|
close();
|
||||||
int fd = STDOUT_FILENO;
|
int fd = STDOUT_FILENO;
|
||||||
if (!force && acc_isatty(fd))
|
if (!force && acc_isatty(fd))
|
||||||
@ -365,17 +250,27 @@ bool OutputFile::openStdout(int flags, bool force)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OutputFile::write(SPAN_0(const void) buf, int len) {
|
||||||
void OutputFile::write(const void *buf, int len)
|
if (!isOpen() || len < 0)
|
||||||
{
|
throwIOException("bad write");
|
||||||
super::write(buf, len);
|
// allow nullptr if len == 0
|
||||||
|
if (len == 0)
|
||||||
|
return;
|
||||||
|
mem_size_assert(1, len); // sanity check
|
||||||
|
errno = 0;
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "write %p %zd (%p) %d\n", buf.raw_ptr(), buf.raw_size_in_bytes(),
|
||||||
|
buf.raw_base(), len);
|
||||||
|
#endif
|
||||||
|
long l = acc_safe_hwrite(_fd, raw_bytes(buf, len), len);
|
||||||
|
if (l != len)
|
||||||
|
throwIOException("write error", errno);
|
||||||
bytes_written += len;
|
bytes_written += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_off_t OutputFile::st_size() const
|
upx_off_t OutputFile::st_size() const {
|
||||||
{
|
if (opt->to_stdout) { // might be a pipe ==> .st_size is invalid
|
||||||
if (opt->to_stdout) { // might be a pipe ==> .st_size is invalid
|
return bytes_written; // too big if seek()+write() instead of rewrite()
|
||||||
return bytes_written; // too big if seek()+write() instead of rewrite()
|
|
||||||
}
|
}
|
||||||
struct stat my_st;
|
struct stat my_st;
|
||||||
my_st.st_size = 0;
|
my_st.st_size = 0;
|
||||||
@ -384,34 +279,13 @@ upx_off_t OutputFile::st_size() const
|
|||||||
return my_st.st_size;
|
return my_st.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OutputFile::rewrite(SPAN_P(const void) buf, int len) {
|
||||||
void OutputFile::write(const MemBuffer *buf, int len)
|
|
||||||
{
|
|
||||||
buf->checkState();
|
|
||||||
assert((unsigned)len <= buf->getSize());
|
|
||||||
write(buf->getVoidPtr(), len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OutputFile::write(const MemBuffer &buf, int len)
|
|
||||||
{
|
|
||||||
write(&buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OutputFile::rewrite(const void *buf, int len)
|
|
||||||
{
|
|
||||||
assert(!opt->to_stdout);
|
assert(!opt->to_stdout);
|
||||||
write(buf, len);
|
write(buf, len);
|
||||||
bytes_written -= len; // restore
|
bytes_written -= len; // restore
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_off_t OutputFile::tell() const
|
upx_off_t OutputFile::seek(upx_off_t off, int whence) {
|
||||||
{
|
|
||||||
return super::tell();
|
|
||||||
}
|
|
||||||
|
|
||||||
upx_off_t OutputFile::seek(upx_off_t off, int whence)
|
|
||||||
{
|
|
||||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||||
assert(!opt->to_stdout);
|
assert(!opt->to_stdout);
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
@ -419,18 +293,18 @@ upx_off_t OutputFile::seek(upx_off_t off, int whence)
|
|||||||
if (bytes_written < off) {
|
if (bytes_written < off) {
|
||||||
bytes_written = off;
|
bytes_written = off;
|
||||||
}
|
}
|
||||||
_length = bytes_written; // cheap, lazy update; needed?
|
_length = bytes_written; // cheap, lazy update; needed?
|
||||||
} break;
|
} break;
|
||||||
case SEEK_END: {
|
case SEEK_END: {
|
||||||
_length = bytes_written; // necessary
|
_length = bytes_written; // necessary
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
return super::seek(off,whence);
|
return super::seek(off, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: fsync() does not exist in some Windows environments.
|
// WARNING: fsync() does not exist in some Windows environments.
|
||||||
// This trick works only on UNIX-like systems.
|
// This trick works only on UNIX-like systems.
|
||||||
//int OutputFile::read(void *buf, int len)
|
// int OutputFile::read(void *buf, int len)
|
||||||
//{
|
//{
|
||||||
// fsync(_fd);
|
// fsync(_fd);
|
||||||
// InputFile infile;
|
// InputFile infile;
|
||||||
@ -439,19 +313,17 @@ upx_off_t OutputFile::seek(upx_off_t off, int whence)
|
|||||||
// return infile.read(buf, len);
|
// return infile.read(buf, len);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
void OutputFile::set_extent(upx_off_t offset, upx_off_t length)
|
void OutputFile::set_extent(upx_off_t offset, upx_off_t length) {
|
||||||
{
|
|
||||||
super::set_extent(offset, length);
|
super::set_extent(offset, length);
|
||||||
bytes_written = 0;
|
bytes_written = 0;
|
||||||
if (0==offset && (upx_off_t)~0u==length) {
|
if (0 == offset && (upx_off_t) ~0u == length) {
|
||||||
if (::fstat(_fd, &st) != 0)
|
if (::fstat(_fd, &st) != 0)
|
||||||
throwIOException(_name, errno);
|
throwIOException(_name, errno);
|
||||||
_length = st.st_size - offset;
|
_length = st.st_size - offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_off_t OutputFile::unset_extent()
|
upx_off_t OutputFile::unset_extent() {
|
||||||
{
|
|
||||||
upx_off_t l = ::lseek(_fd, 0, SEEK_END);
|
upx_off_t l = ::lseek(_fd, 0, SEEK_END);
|
||||||
if (l < 0)
|
if (l < 0)
|
||||||
throwIOException("lseek error", errno);
|
throwIOException("lseek error", errno);
|
||||||
@ -461,44 +333,14 @@ upx_off_t OutputFile::unset_extent()
|
|||||||
return _length;
|
return _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputFile::dump(const char *name, const void *buf, int len, int flags)
|
void OutputFile::dump(const char *name, SPAN_P(const void) buf, int len, int flags) {
|
||||||
{
|
|
||||||
if (flags < 0)
|
if (flags < 0)
|
||||||
flags = O_CREAT | O_TRUNC;
|
flags = O_CREAT | O_TRUNC;
|
||||||
flags |= O_WRONLY | O_BINARY;
|
flags |= O_WRONLY | O_BINARY;
|
||||||
OutputFile f;
|
OutputFile f;
|
||||||
f.open(name, flags, 0600);
|
f.open(name, flags, 0600);
|
||||||
f.write(buf, len);
|
f.write(raw_bytes(buf, len), len);
|
||||||
f.closex();
|
f.closex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
MemoryOutputFile::MemoryOutputFile() :
|
|
||||||
b(nullptr), b_size(0), b_pos(0), bytes_written(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MemoryOutputFile::write(const void *buf, int len)
|
|
||||||
{
|
|
||||||
if (!isOpen() || len < 0)
|
|
||||||
throwIOException("bad write");
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
if (b_pos + len > b_size)
|
|
||||||
throwIOException("write error",ENOSPC);
|
|
||||||
memcpy(b + b_pos, buf, len);
|
|
||||||
b_pos += len;
|
|
||||||
bytes_written += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* if 0 */
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|||||||
161
src/file.h
161
src/file.h
@ -25,165 +25,110 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __UPX_FILE_H
|
#ifndef UPX_FILE_H__
|
||||||
#define __UPX_FILE_H 1
|
#define UPX_FILE_H__ 1
|
||||||
|
|
||||||
class MemBuffer;
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class File
|
class FileBase {
|
||||||
{
|
|
||||||
protected:
|
|
||||||
File() { }
|
|
||||||
virtual ~File() { }
|
|
||||||
public:
|
|
||||||
static void chmod(const char *name, int mode);
|
|
||||||
static void rename(const char *old_, const char *new_);
|
|
||||||
static void unlink(const char *name);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class FileBase : public File
|
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
FileBase();
|
FileBase();
|
||||||
virtual ~FileBase();
|
virtual ~FileBase();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool close();
|
bool close();
|
||||||
virtual void closex();
|
void closex();
|
||||||
virtual bool isOpen() const { return _fd >= 0; }
|
bool isOpen() const { return _fd >= 0; }
|
||||||
int getFd() const { return _fd; }
|
int getFd() const { return _fd; }
|
||||||
const char *getName() const { return _name; }
|
const char *getName() const { return _name; }
|
||||||
virtual upx_off_t st_size() const; // { return _length; }
|
|
||||||
|
virtual upx_off_t seek(upx_off_t off, int whence);
|
||||||
|
upx_off_t tell() const;
|
||||||
|
virtual upx_off_t st_size() const; // { return _length; }
|
||||||
virtual void set_extent(upx_off_t offset, upx_off_t length);
|
virtual void set_extent(upx_off_t offset, upx_off_t length);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// static file-related util functions
|
||||||
|
static void chmod(const char *name, int mode);
|
||||||
|
static void rename(const char *old_, const char *new_);
|
||||||
|
static void unlink(const char *name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool do_sopen();
|
bool do_sopen();
|
||||||
virtual int read(void *buf, int len);
|
int _fd = -1;
|
||||||
virtual int readx(void *buf, int len);
|
int _flags = 0;
|
||||||
virtual void write(const void *buf, int len);
|
int _shflags = 0;
|
||||||
virtual upx_off_t seek(upx_off_t off, int whence);
|
int _mode = 0;
|
||||||
virtual upx_off_t tell() const;
|
const char *_name = nullptr;
|
||||||
|
upx_off_t _offset = 0;
|
||||||
|
upx_off_t _length = 0;
|
||||||
|
|
||||||
int _fd;
|
|
||||||
int _flags;
|
|
||||||
int _shflags;
|
|
||||||
int _mode;
|
|
||||||
const char *_name;
|
|
||||||
upx_off_t _offset;
|
|
||||||
upx_off_t _length;
|
|
||||||
public:
|
public:
|
||||||
struct stat st;
|
struct stat st = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class InputFile final : public FileBase
|
class InputFile final : public FileBase {
|
||||||
{
|
|
||||||
typedef FileBase super;
|
typedef FileBase super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InputFile();
|
InputFile();
|
||||||
virtual ~InputFile();
|
virtual ~InputFile() {}
|
||||||
|
|
||||||
virtual void sopen(const char *name, int flags, int shflags);
|
void sopen(const char *name, int flags, int shflags);
|
||||||
virtual void open(const char *name, int flags)
|
void open(const char *name, int flags) { sopen(name, flags, -1); }
|
||||||
{
|
|
||||||
sopen(name, flags, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int read(void *buf, int len) override;
|
int read(SPAN_P(void) buf, int len);
|
||||||
virtual int readx(void *buf, int len) override;
|
int readx(SPAN_P(void) buf, int len);
|
||||||
virtual int read(MemBuffer *buf, int len);
|
|
||||||
virtual int readx(MemBuffer *buf, int len);
|
|
||||||
virtual int read(MemBuffer &buf, int len);
|
|
||||||
virtual int readx(MemBuffer &buf, int len);
|
|
||||||
|
|
||||||
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
||||||
virtual upx_off_t tell() const override;
|
upx_off_t st_size_orig() const;
|
||||||
virtual upx_off_t st_size_orig() const;
|
|
||||||
protected:
|
|
||||||
upx_off_t _length_orig;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
upx_off_t _length_orig = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class OutputFile final : public FileBase
|
class OutputFile final : public FileBase {
|
||||||
{
|
|
||||||
typedef FileBase super;
|
typedef FileBase super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OutputFile();
|
OutputFile();
|
||||||
virtual ~OutputFile();
|
virtual ~OutputFile() {}
|
||||||
|
|
||||||
virtual void sopen(const char *name, int flags, int shflags, int mode);
|
void sopen(const char *name, int flags, int shflags, int mode);
|
||||||
virtual void open(const char *name, int flags, int mode)
|
void open(const char *name, int flags, int mode) { sopen(name, flags, -1, mode); }
|
||||||
{
|
bool openStdout(int flags = 0, bool force = false);
|
||||||
sopen(name, flags, -1, mode);
|
|
||||||
}
|
|
||||||
virtual bool openStdout(int flags=0, bool force=false);
|
|
||||||
|
|
||||||
virtual void write(const void *buf, int len) override;
|
// info: allow nullptr if len == 0
|
||||||
virtual void write(const MemBuffer *buf, int len);
|
void write(SPAN_0(const void) buf, int len);
|
||||||
virtual void write(const MemBuffer &buf, int len);
|
|
||||||
|
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
||||||
|
virtual upx_off_t st_size() const override; // { return _length; }
|
||||||
virtual void set_extent(upx_off_t offset, upx_off_t length) override;
|
virtual void set_extent(upx_off_t offset, upx_off_t length) override;
|
||||||
virtual upx_off_t unset_extent(); // returns actual length
|
upx_off_t unset_extent(); // returns actual length
|
||||||
|
|
||||||
upx_off_t getBytesWritten() const { return bytes_written; }
|
upx_off_t getBytesWritten() const { return bytes_written; }
|
||||||
virtual upx_off_t st_size() const override; // { return _length; }
|
|
||||||
|
|
||||||
// FIXME - these won't work when using the '--stdout' option
|
// FIXME - these won't work when using the '--stdout' option
|
||||||
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
void rewrite(SPAN_P(const void) buf, int len);
|
||||||
virtual upx_off_t tell() const override;
|
|
||||||
virtual void rewrite(const void *buf, int len);
|
|
||||||
|
|
||||||
// util
|
// util
|
||||||
static void dump(const char *name, const void *buf, int len, int flags=-1);
|
static void dump(const char *name, SPAN_P(const void) buf, int len, int flags = -1);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
upx_off_t bytes_written;
|
upx_off_t bytes_written = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#if 0 /* NOT USED */
|
|
||||||
class MemoryOutputFile : public FileBase
|
|
||||||
{
|
|
||||||
typedef FileBase super;
|
|
||||||
public:
|
|
||||||
MemoryOutputFile();
|
|
||||||
virtual ~MemoryOutputFile() { b = nullptr; }
|
|
||||||
|
|
||||||
virtual bool close() { b = nullptr; return true; }
|
|
||||||
virtual bool isOpen() const { return b != nullptr; }
|
|
||||||
virtual void open(void *buf, unsigned size)
|
|
||||||
{ b = (upx_bytep) buf; b_size = size; }
|
|
||||||
|
|
||||||
virtual void write(const void *buf, int len);
|
|
||||||
|
|
||||||
upx_off_t getBytesWritten() const { return bytes_written; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
upx_bytep b;
|
|
||||||
unsigned b_size;
|
|
||||||
unsigned b_pos;
|
|
||||||
upx_off_t bytes_written;
|
|
||||||
};
|
|
||||||
#endif /* if 0 */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "mem.h"
|
#include "util/membuffer.h"
|
||||||
#include "lefile.h"
|
#include "lefile.h"
|
||||||
|
|
||||||
|
|
||||||
@ -77,7 +77,8 @@ LeFile::~LeFile()
|
|||||||
|
|
||||||
void LeFile::readObjectTable()
|
void LeFile::readObjectTable()
|
||||||
{
|
{
|
||||||
iobject_table = new le_object_table_entry_t[soobject_table = objects];
|
soobject_table = objects;
|
||||||
|
iobject_table = New(le_object_table_entry_t, soobject_table);
|
||||||
fif->seek(le_offset + ih.object_table_offset,SEEK_SET);
|
fif->seek(le_offset + ih.object_table_offset,SEEK_SET);
|
||||||
fif->readx(iobject_table,sizeof(*iobject_table)*objects);
|
fif->readx(iobject_table,sizeof(*iobject_table)*objects);
|
||||||
}
|
}
|
||||||
@ -92,7 +93,8 @@ void LeFile::writeObjectTable()
|
|||||||
|
|
||||||
void LeFile::readPageMap()
|
void LeFile::readPageMap()
|
||||||
{
|
{
|
||||||
ipm_entries = new le_pagemap_entry_t[sopm_entries = pages];
|
sopm_entries = pages;
|
||||||
|
ipm_entries = New(le_pagemap_entry_t, sopm_entries);
|
||||||
fif->seek(le_offset + ih.object_pagemap_offset,SEEK_SET);
|
fif->seek(le_offset + ih.object_pagemap_offset,SEEK_SET);
|
||||||
fif->readx(ipm_entries,sizeof(*ipm_entries)*pages);
|
fif->readx(ipm_entries,sizeof(*ipm_entries)*pages);
|
||||||
|
|
||||||
@ -112,7 +114,7 @@ void LeFile::writePageMap()
|
|||||||
void LeFile::readResidentNames()
|
void LeFile::readResidentNames()
|
||||||
{
|
{
|
||||||
sores_names = ih.entry_table_offset - ih.resident_names_offset;
|
sores_names = ih.entry_table_offset - ih.resident_names_offset;
|
||||||
ires_names = new upx_byte[sores_names];
|
ires_names = New(upx_byte, sores_names);
|
||||||
fif->seek(le_offset+ih.resident_names_offset,SEEK_SET);
|
fif->seek(le_offset+ih.resident_names_offset,SEEK_SET);
|
||||||
fif->readx(ires_names,sores_names);
|
fif->readx(ires_names,sores_names);
|
||||||
}
|
}
|
||||||
@ -129,7 +131,7 @@ void LeFile::readEntryTable()
|
|||||||
{
|
{
|
||||||
soentries = ih.fixup_page_table_offset - ih.entry_table_offset;
|
soentries = ih.fixup_page_table_offset - ih.entry_table_offset;
|
||||||
fif->seek(le_offset + ih.entry_table_offset,SEEK_SET);
|
fif->seek(le_offset + ih.entry_table_offset,SEEK_SET);
|
||||||
ientries = new upx_byte[soentries];
|
ientries = New(upx_byte, soentries);
|
||||||
fif->readx(ientries,soentries);
|
fif->readx(ientries,soentries);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +145,8 @@ void LeFile::writeEntryTable()
|
|||||||
|
|
||||||
void LeFile::readFixupPageTable()
|
void LeFile::readFixupPageTable()
|
||||||
{
|
{
|
||||||
ifpage_table = new unsigned[sofpage_table = 1+pages];
|
sofpage_table = 1+pages;
|
||||||
|
ifpage_table = New(unsigned, sofpage_table);
|
||||||
fif->seek(le_offset + ih.fixup_page_table_offset,SEEK_SET);
|
fif->seek(le_offset + ih.fixup_page_table_offset,SEEK_SET);
|
||||||
fif->readx(ifpage_table,4*sofpage_table);
|
fif->readx(ifpage_table,4*sofpage_table);
|
||||||
}
|
}
|
||||||
@ -159,7 +162,7 @@ void LeFile::writeFixupPageTable()
|
|||||||
void LeFile::readFixups()
|
void LeFile::readFixups()
|
||||||
{
|
{
|
||||||
sofixups = get_le32(ifpage_table+pages)-get_le32(ifpage_table);
|
sofixups = get_le32(ifpage_table+pages)-get_le32(ifpage_table);
|
||||||
ifixups = new upx_byte[sofixups];
|
ifixups = New(upx_byte, sofixups);
|
||||||
fif->seek(le_offset + ih.fixup_record_table_offset,SEEK_SET);
|
fif->seek(le_offset + ih.fixup_record_table_offset,SEEK_SET);
|
||||||
fif->readx(ifixups,sofixups);
|
fif->readx(ifixups,sofixups);
|
||||||
}
|
}
|
||||||
@ -187,8 +190,9 @@ unsigned LeFile::getImageSize() const
|
|||||||
void LeFile::readImage()
|
void LeFile::readImage()
|
||||||
{
|
{
|
||||||
soimage = pages*mps;
|
soimage = pages*mps;
|
||||||
iimage.alloc(soimage);
|
mb_iimage.alloc(soimage);
|
||||||
memset(iimage,0,soimage);
|
mb_iimage.clear();
|
||||||
|
iimage = mb_iimage;
|
||||||
|
|
||||||
unsigned ic,jc;
|
unsigned ic,jc;
|
||||||
for (ic = jc = 0; ic < pages; ic++)
|
for (ic = jc = 0; ic < pages; ic++)
|
||||||
@ -197,7 +201,8 @@ void LeFile::readImage()
|
|||||||
{
|
{
|
||||||
fif->seek(ih.data_pages_offset + exe_offset +
|
fif->seek(ih.data_pages_offset + exe_offset +
|
||||||
(ipm_entries[ic].m*0x100 + ipm_entries[ic].l-1) * mps,SEEK_SET);
|
(ipm_entries[ic].m*0x100 + ipm_entries[ic].l-1) * mps,SEEK_SET);
|
||||||
fif->readx(iimage+jc,ic != pages-1 ? mps : ih.bytes_on_last_page);
|
auto bytes = ic != pages-1 ? mps : ih.bytes_on_last_page;
|
||||||
|
fif->readx(raw_bytes(iimage+jc, bytes), bytes);
|
||||||
}
|
}
|
||||||
jc += mps;
|
jc += mps;
|
||||||
}
|
}
|
||||||
@ -207,7 +212,7 @@ void LeFile::readImage()
|
|||||||
void LeFile::writeImage()
|
void LeFile::writeImage()
|
||||||
{
|
{
|
||||||
if (fof && oimage != nullptr)
|
if (fof && oimage != nullptr)
|
||||||
fof->write(oimage, soimage);
|
fof->write(raw_bytes(oimage, soimage), soimage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -215,7 +220,8 @@ void LeFile::readNonResidentNames()
|
|||||||
{
|
{
|
||||||
if (ih.non_resident_name_table_length)
|
if (ih.non_resident_name_table_length)
|
||||||
{
|
{
|
||||||
inonres_names = new upx_byte[sononres_names = ih.non_resident_name_table_length];
|
sononres_names = ih.non_resident_name_table_length;
|
||||||
|
inonres_names = New(upx_byte, sononres_names);
|
||||||
fif->seek(exe_offset+ih.non_resident_name_table_offset,SEEK_SET);
|
fif->seek(exe_offset+ih.non_resident_name_table_offset,SEEK_SET);
|
||||||
fif->readx(inonres_names,sononres_names);
|
fif->readx(inonres_names,sononres_names);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ class OutputFile;
|
|||||||
|
|
||||||
class LeFile
|
class LeFile
|
||||||
{
|
{
|
||||||
public:
|
protected:
|
||||||
LeFile(InputFile *);
|
LeFile(InputFile *);
|
||||||
virtual ~LeFile();
|
virtual ~LeFile();
|
||||||
|
|
||||||
@ -198,8 +198,10 @@ protected:
|
|||||||
upx_byte *ofixups;
|
upx_byte *ofixups;
|
||||||
upx_byte *inonres_names;
|
upx_byte *inonres_names;
|
||||||
upx_byte *ononres_names;
|
upx_byte *ononres_names;
|
||||||
MemBuffer iimage;
|
MemBuffer mb_iimage;
|
||||||
MemBuffer oimage;
|
SPAN_0(upx_byte) iimage = nullptr;
|
||||||
|
MemBuffer mb_oimage;
|
||||||
|
SPAN_0(upx_byte) oimage = nullptr;
|
||||||
upx_byte *ientries;
|
upx_byte *ientries;
|
||||||
upx_byte *oentries;
|
upx_byte *oentries;
|
||||||
|
|
||||||
|
|||||||
@ -1122,7 +1122,7 @@ int upx_main(int argc, char *argv[]) {
|
|||||||
argv0 = argv[0];
|
argv0 = argv[0];
|
||||||
|
|
||||||
upx_compiler_sanity_check();
|
upx_compiler_sanity_check();
|
||||||
if (!upx_doctest_check()) {
|
if (!upx_doctest_check(argc, argv)) {
|
||||||
fprintf(stderr, "%s: internal error: doctest failed\n", argv0);
|
fprintf(stderr, "%s: internal error: doctest failed\n", argv0);
|
||||||
e_exit(EXIT_INIT);
|
e_exit(EXIT_INIT);
|
||||||
}
|
}
|
||||||
|
|||||||
88
src/mem.h
88
src/mem.h
@ -1,88 +0,0 @@
|
|||||||
/* mem.h --
|
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
|
||||||
|
|
||||||
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
|
||||||
Copyright (C) 1996-2022 Laszlo Molnar
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
|
||||||
and/or modify them under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; see the file COPYING.
|
|
||||||
If not, write to the Free Software Foundation, Inc.,
|
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
|
||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __UPX_MEM_H
|
|
||||||
#define __UPX_MEM_H 1
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
class MemBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MemBuffer() : b(nullptr), b_size(0) { }
|
|
||||||
explicit MemBuffer(upx_uint64_t size);
|
|
||||||
~MemBuffer();
|
|
||||||
|
|
||||||
static unsigned getSizeForCompression(unsigned uncompressed_size, unsigned extra=0);
|
|
||||||
static unsigned getSizeForUncompression(unsigned uncompressed_size, unsigned extra=0);
|
|
||||||
|
|
||||||
void alloc(upx_uint64_t size);
|
|
||||||
void allocForCompression(unsigned uncompressed_size, unsigned extra=0);
|
|
||||||
void allocForUncompression(unsigned uncompressed_size, unsigned extra=0);
|
|
||||||
|
|
||||||
void dealloc();
|
|
||||||
|
|
||||||
void checkState() const;
|
|
||||||
|
|
||||||
unsigned getSize() const { return b_size; }
|
|
||||||
|
|
||||||
operator unsigned char * () { return b; }
|
|
||||||
operator const unsigned char * () const { return b; }
|
|
||||||
|
|
||||||
void *getVoidPtr() { return (void *) b; }
|
|
||||||
const void *getVoidPtr() const { return (const void *) b; }
|
|
||||||
|
|
||||||
void fill(unsigned off, unsigned len, int value);
|
|
||||||
void clear(unsigned off, unsigned len) { fill(off, len, 0); }
|
|
||||||
void clear() { fill(0, b_size, 0); }
|
|
||||||
|
|
||||||
// If the entire range [skip, take+skip) is inside the buffer,
|
|
||||||
// then return &b[skip]; else throwCantPack(sprintf(errfmt, skip, take)).
|
|
||||||
// This is similar to BoundedPtr, except only checks once.
|
|
||||||
unsigned char *subref(char const *errfmt, unsigned skip, unsigned take);
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned char *b;
|
|
||||||
unsigned b_size;
|
|
||||||
|
|
||||||
static unsigned global_alloc_counter;
|
|
||||||
|
|
||||||
// disable copy, assignment and move assignment
|
|
||||||
MemBuffer(const MemBuffer &) = delete;
|
|
||||||
MemBuffer& operator= (const MemBuffer &) = delete;
|
|
||||||
MemBuffer& operator= (MemBuffer &&) = delete;
|
|
||||||
// disable dynamic allocation
|
|
||||||
ACC_CXX_DISABLE_NEW_DELETE
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* already included */
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
|
||||||
@ -25,8 +25,9 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UPX_OPTIONS_H
|
#pragma once
|
||||||
#define __UPX_OPTIONS_H 1
|
#ifndef UPX_OPTIONS_H__
|
||||||
|
#define UPX_OPTIONS_H__ 1
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// globals
|
// globals
|
||||||
|
|||||||
@ -34,35 +34,35 @@
|
|||||||
// djgpp2/coff
|
// djgpp2/coff
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class PackDjgpp2 : public Packer
|
class PackDjgpp2 final : public Packer
|
||||||
{
|
{
|
||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackDjgpp2(InputFile *f);
|
PackDjgpp2(InputFile *f);
|
||||||
virtual int getVersion() const { return 14; }
|
virtual int getVersion() const override { return 14; }
|
||||||
virtual int getFormat() const { return UPX_F_DJGPP2_COFF; }
|
virtual int getFormat() const override { return UPX_F_DJGPP2_COFF; }
|
||||||
virtual const char *getName() const { return "djgpp2/coff"; }
|
virtual const char *getName() const override { return "djgpp2/coff"; }
|
||||||
virtual const char *getFullName(const options_t *) const { return "i386-dos32.djgpp2.coff"; }
|
virtual const char *getFullName(const options_t *) const override { return "i386-dos32.djgpp2.coff"; }
|
||||||
virtual const int *getCompressionMethods(int method, int level) const;
|
virtual const int *getCompressionMethods(int method, int level) const override;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const override;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo) override;
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo) override;
|
||||||
|
|
||||||
virtual bool canPack();
|
virtual bool canPack() override;
|
||||||
virtual int canUnpack();
|
virtual int canUnpack() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void handleStub(OutputFile *fo);
|
void handleStub(OutputFile *fo);
|
||||||
virtual int readFileHeader();
|
int readFileHeader();
|
||||||
|
|
||||||
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
||||||
const upx_bytep tbuf,
|
const upx_bytep tbuf,
|
||||||
unsigned range = 0,
|
unsigned range = 0,
|
||||||
unsigned upper_limit = ~0u) const;
|
unsigned upper_limit = ~0u) const override;
|
||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft) override;
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const override;
|
||||||
|
|
||||||
unsigned coff_offset;
|
unsigned coff_offset;
|
||||||
|
|
||||||
|
|||||||
@ -607,8 +607,8 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// g++ 3.1 does not like the following line...
|
// g++ 3.1 does not like the following line...
|
||||||
// oh.relocoffs = offsetof(exe_header_t, firstreloc);
|
oh.relocoffs = offsetof(exe_header_t, firstreloc);
|
||||||
oh.relocoffs = ptr_diff(&oh.firstreloc, &oh);
|
//oh.relocoffs = ptr_udiff_bytes(&oh.firstreloc, &oh);
|
||||||
|
|
||||||
linker->defineSymbol("destination_segment", oh.ss - ph.c_len / 16 - e_len / 16);
|
linker->defineSymbol("destination_segment", oh.ss - ph.c_len / 16 - e_len / 16);
|
||||||
linker->defineSymbol("source_segment", e_len / 16 + (copysize - firstcopy) / 16);
|
linker->defineSymbol("source_segment", e_len / 16 + (copysize - firstcopy) / 16);
|
||||||
@ -658,7 +658,7 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
verifyOverlappingDecompression();
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, ih_overlay, &obuf);
|
copyOverlay(fo, ih_overlay, obuf);
|
||||||
//fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
|
//fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
@ -710,7 +710,7 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
const unsigned char flag = ibuf[imagesize];
|
const unsigned char flag = ibuf[imagesize];
|
||||||
|
|
||||||
unsigned relocn = 0;
|
unsigned relocn = 0;
|
||||||
upx_byte *relocs = obuf + ph.u_len;
|
SPAN_S_VAR(upx_byte, relocs, obuf + ph.u_len, obuf);
|
||||||
|
|
||||||
MemBuffer wrkmem;
|
MemBuffer wrkmem;
|
||||||
if (!(flag & NORELOC))
|
if (!(flag & NORELOC))
|
||||||
@ -721,7 +721,7 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
wrkmem.alloc(4*MAXRELOCS);
|
wrkmem.alloc(4*MAXRELOCS);
|
||||||
unsigned es = 0, ones = get_le16(relocs);
|
unsigned es = 0, ones = get_le16(relocs);
|
||||||
const unsigned seghi = get_le16(relocs+2);
|
const unsigned seghi = get_le16(relocs+2);
|
||||||
const upx_byte *p = relocs + 4;
|
SPAN_S_VAR(const upx_byte, p, relocs + 4);
|
||||||
|
|
||||||
while (ones)
|
while (ones)
|
||||||
{
|
{
|
||||||
@ -739,10 +739,11 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
dorel = true;
|
dorel = true;
|
||||||
if (*p == 0)
|
if (*p == 0)
|
||||||
{
|
{
|
||||||
const upx_byte *q;
|
SPAN_S_VAR(const upx_byte, q, obuf);
|
||||||
|
|
||||||
for (q = obuf+es*16+di; !(*q == 0x9a && get_le16(q+3) <= seghi); q++)
|
for (q = obuf+es*16+di; !(*q == 0x9a && get_le16(q+3) <= seghi); q++)
|
||||||
;
|
;
|
||||||
di = ptr_diff(q, obuf+es*16) + 3;
|
di = ptr_diff_bytes(q, obuf+es*16) + 3;
|
||||||
}
|
}
|
||||||
else if (*p == 1)
|
else if (*p == 1)
|
||||||
{
|
{
|
||||||
@ -768,7 +769,7 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
set_le32(wrkmem+4*relocn++,0);
|
set_le32(wrkmem+4*relocn++,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned outputlen = ptr_diff(relocs, obuf) + sizeof(oh) + relocn*4;
|
unsigned outputlen = ptr_udiff_bytes(relocs, obuf) + sizeof(oh) + relocn*4;
|
||||||
oh.m512 = outputlen & 511;
|
oh.m512 = outputlen & 511;
|
||||||
oh.p512 = (outputlen + 511) >> 9;
|
oh.p512 = (outputlen + 511) >> 9;
|
||||||
oh.headsize16 = 2+relocn/4;
|
oh.headsize16 = 2+relocn/4;
|
||||||
@ -800,10 +801,10 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
fo->write(&oh,sizeof(oh));
|
fo->write(&oh,sizeof(oh));
|
||||||
if (relocn)
|
if (relocn)
|
||||||
fo->write(wrkmem,relocn*4);
|
fo->write(wrkmem,relocn*4);
|
||||||
fo->write(obuf, ptr_diff(relocs, obuf));
|
fo->write(obuf, ptr_diff_bytes(relocs, obuf));
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, ih_overlay, &obuf);
|
copyOverlay(fo, ih_overlay, obuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1456,8 +1456,6 @@ static const
|
|||||||
static const
|
static const
|
||||||
#include "stub/armeb.v4a-linux.elf-fold.h"
|
#include "stub/armeb.v4a-linux.elf-fold.h"
|
||||||
|
|
||||||
#include "mem.h"
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackLinuxElf32armBe::buildLoader(Filter const *ft)
|
PackLinuxElf32armBe::buildLoader(Filter const *ft)
|
||||||
{
|
{
|
||||||
@ -4611,7 +4609,7 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
|
|||||||
unsigned tmp = sz_pack2 + get_te32(&elfout.phdr[C_TEXT].p_vaddr);
|
unsigned tmp = sz_pack2 + get_te32(&elfout.phdr[C_TEXT].p_vaddr);
|
||||||
tmp |= (Elf32_Ehdr::EM_ARM==e_machine); // THUMB mode
|
tmp |= (Elf32_Ehdr::EM_ARM==e_machine); // THUMB mode
|
||||||
set_te32(&tmp, tmp);
|
set_te32(&tmp, tmp);
|
||||||
fo->seek(ptr_udiff(&jni_onload_sym->st_value, file_image), SEEK_SET);
|
fo->seek(ptr_udiff_bytes(&jni_onload_sym->st_value, file_image), SEEK_SET);
|
||||||
fo->rewrite(&tmp, sizeof(tmp));
|
fo->rewrite(&tmp, sizeof(tmp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1529,7 +1529,7 @@ void PackMachBase<T>::unpack(OutputFile *fo)
|
|||||||
if (is_bad_linker_command( ((Mach_command const *)ptr)->cmd, cmdsize,
|
if (is_bad_linker_command( ((Mach_command const *)ptr)->cmd, cmdsize,
|
||||||
headway, lc_seg, sizeof(Addr))) {
|
headway, lc_seg, sizeof(Addr))) {
|
||||||
char msg[50]; snprintf(msg, sizeof(msg),
|
char msg[50]; snprintf(msg, sizeof(msg),
|
||||||
"bad packed Mach load_command @%#x", ptr_udiff(ptr, mhdr));
|
"bad packed Mach load_command @%#x", ptr_udiff_bytes(ptr, mhdr));
|
||||||
throwCantUnpack(msg);
|
throwCantUnpack(msg);
|
||||||
}
|
}
|
||||||
memcpy(&msegcmd[j], ptr, umin(sizeof(Mach_segment_command), cmdsize));
|
memcpy(&msegcmd[j], ptr, umin(sizeof(Mach_segment_command), cmdsize));
|
||||||
@ -1905,7 +1905,7 @@ template <class T>
|
|||||||
upx_uint64_t PackMachBase<T>::get_mod_init_func(Mach_segment_command const *segptr)
|
upx_uint64_t PackMachBase<T>::get_mod_init_func(Mach_segment_command const *segptr)
|
||||||
{
|
{
|
||||||
for (Mach_section_command const *secptr = (Mach_section_command const *)(1+ segptr);
|
for (Mach_section_command const *secptr = (Mach_section_command const *)(1+ segptr);
|
||||||
ptr_udiff(secptr, segptr) < segptr->cmdsize;
|
ptr_udiff_bytes(secptr, segptr) < segptr->cmdsize;
|
||||||
++secptr
|
++secptr
|
||||||
) {
|
) {
|
||||||
if (sizeof(Addr) == secptr->size
|
if (sizeof(Addr) == secptr->size
|
||||||
|
|||||||
38
src/p_ps1.h
38
src/p_ps1.h
@ -38,34 +38,34 @@
|
|||||||
// ps1/exe
|
// ps1/exe
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class PackPs1 : public Packer
|
class PackPs1 final : public Packer
|
||||||
{
|
{
|
||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackPs1(InputFile *f);
|
PackPs1(InputFile *f);
|
||||||
virtual int getVersion() const { return 13; }
|
virtual int getVersion() const override { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_PS1_EXE; }
|
virtual int getFormat() const override { return UPX_F_PS1_EXE; }
|
||||||
virtual const char *getName() const { return "ps1/exe"; }
|
virtual const char *getName() const override { return "ps1/exe"; }
|
||||||
virtual const char *getFullName(const options_t *) const { return "mipsel.r3000-ps1"; }
|
virtual const char *getFullName(const options_t *) const override { return "mipsel.r3000-ps1"; }
|
||||||
virtual const int *getCompressionMethods(int method, int level) const;
|
virtual const int *getCompressionMethods(int method, int level) const override;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const override;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo) override;
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo) override;
|
||||||
|
|
||||||
virtual bool canPack();
|
virtual bool canPack() override;
|
||||||
virtual int canUnpack();
|
virtual int canUnpack() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void putBkupHeader(const unsigned char *src, unsigned char *dst, unsigned *len);
|
void putBkupHeader(const unsigned char *src, unsigned char *dst, unsigned *len);
|
||||||
virtual bool getBkupHeader(unsigned char *src, unsigned char * dst);
|
bool getBkupHeader(unsigned char *src, unsigned char * dst);
|
||||||
virtual bool readBkupHeader();
|
bool readBkupHeader();
|
||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft) override;
|
||||||
virtual bool findBssSection();
|
bool findBssSection();
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const override;
|
||||||
|
|
||||||
virtual int readFileHeader();
|
int readFileHeader();
|
||||||
virtual bool checkFileHeader();
|
bool checkFileHeader();
|
||||||
|
|
||||||
__packed_struct(ps1_exe_t)
|
__packed_struct(ps1_exe_t)
|
||||||
// ident string
|
// ident string
|
||||||
|
|||||||
@ -235,9 +235,7 @@ void PackTmt::pack(OutputFile *fo)
|
|||||||
{
|
{
|
||||||
for (unsigned ic=4; ic<=rsize; ic+=4)
|
for (unsigned ic=4; ic<=rsize; ic+=4)
|
||||||
set_le32(wrkmem+ic,get_le32(wrkmem+ic)-4);
|
set_le32(wrkmem+ic,get_le32(wrkmem+ic)-4);
|
||||||
relocsize = ptr_diff(
|
relocsize = optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,file_size,1,&big_relocs);
|
||||||
optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,file_size,1,&big_relocs),
|
|
||||||
wrkmem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wrkmem[relocsize++] = 0;
|
wrkmem[relocsize++] = 0;
|
||||||
@ -300,7 +298,7 @@ void PackTmt::pack(OutputFile *fo)
|
|||||||
verifyOverlappingDecompression();
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, obuf);
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
@ -332,7 +330,7 @@ void PackTmt::unpack(OutputFile *fo)
|
|||||||
|
|
||||||
// decode relocations
|
// decode relocations
|
||||||
const unsigned osize = ph.u_len - get_le32(obuf+ph.u_len-4);
|
const unsigned osize = ph.u_len - get_le32(obuf+ph.u_len-4);
|
||||||
upx_byte *relocs = obuf + osize;
|
SPAN_P_VAR(upx_byte, relocs, obuf + osize);
|
||||||
const unsigned origstart = get_le32(obuf+ph.u_len-8);
|
const unsigned origstart = get_le32(obuf+ph.u_len-8);
|
||||||
|
|
||||||
// unfilter
|
// unfilter
|
||||||
@ -343,12 +341,13 @@ void PackTmt::unpack(OutputFile *fo)
|
|||||||
ft.cto = (unsigned char) ph.filter_cto;
|
ft.cto = (unsigned char) ph.filter_cto;
|
||||||
if (ph.version < 11)
|
if (ph.version < 11)
|
||||||
ft.cto = (unsigned char) (get_le32(obuf+ph.u_len-12) >> 24);
|
ft.cto = (unsigned char) (get_le32(obuf+ph.u_len-12) >> 24);
|
||||||
ft.unfilter(obuf, ptr_diff(relocs, obuf));
|
ft.unfilter(obuf, ptr_udiff_bytes(relocs, obuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode relocations
|
// decode relocations
|
||||||
MemBuffer wrkmem;
|
MemBuffer mb_wrkmem;
|
||||||
unsigned relocn = unoptimizeReloc32(&relocs,obuf,&wrkmem,1);
|
unsigned relocn = unoptimizeReloc32(relocs, obuf, mb_wrkmem, true);
|
||||||
|
SPAN_S_VAR(upx_byte, wrkmem, mb_wrkmem);
|
||||||
for (unsigned ic = 0; ic < relocn; ic++)
|
for (unsigned ic = 0; ic < relocn; ic++)
|
||||||
set_le32(wrkmem+ic*4,get_le32(wrkmem+ic*4)+4);
|
set_le32(wrkmem+ic*4,get_le32(wrkmem+ic*4)+4);
|
||||||
|
|
||||||
@ -366,11 +365,11 @@ void PackTmt::unpack(OutputFile *fo)
|
|||||||
{
|
{
|
||||||
fo->write(&oh,sizeof(oh));
|
fo->write(&oh,sizeof(oh));
|
||||||
fo->write(obuf,osize);
|
fo->write(obuf,osize);
|
||||||
fo->write(wrkmem,relocn*4);
|
fo->write(raw_bytes(wrkmem,relocn*4), relocn*4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, obuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|||||||
30
src/p_tmt.h
30
src/p_tmt.h
@ -34,33 +34,33 @@
|
|||||||
// tmt/adam
|
// tmt/adam
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class PackTmt : public Packer
|
class PackTmt final : public Packer
|
||||||
{
|
{
|
||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackTmt(InputFile *f);
|
PackTmt(InputFile *f);
|
||||||
virtual int getVersion() const { return 13; }
|
virtual int getVersion() const override { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_TMT_ADAM; }
|
virtual int getFormat() const override { return UPX_F_TMT_ADAM; }
|
||||||
virtual const char *getName() const { return "tmt/adam"; }
|
virtual const char *getName() const override { return "tmt/adam"; }
|
||||||
virtual const char *getFullName(const options_t *) const { return "i386-dos32.tmt.adam"; }
|
virtual const char *getFullName(const options_t *) const override { return "i386-dos32.tmt.adam"; }
|
||||||
virtual const int *getCompressionMethods(int method, int level) const;
|
virtual const int *getCompressionMethods(int method, int level) const override;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const override;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo) override;
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo) override;
|
||||||
|
|
||||||
virtual bool canPack();
|
virtual bool canPack() override;
|
||||||
virtual int canUnpack();
|
virtual int canUnpack() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int readFileHeader();
|
int readFileHeader();
|
||||||
|
|
||||||
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
||||||
const upx_bytep tbuf,
|
const upx_bytep tbuf,
|
||||||
unsigned range = 0,
|
unsigned range = 0,
|
||||||
unsigned upper_limit = ~0u) const;
|
unsigned upper_limit = ~0u) const override;
|
||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft) override;
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const override;
|
||||||
|
|
||||||
unsigned adam_offset;
|
unsigned adam_offset;
|
||||||
int big_relocs;
|
int big_relocs;
|
||||||
|
|||||||
@ -662,7 +662,7 @@ void PackTos::pack(OutputFile *fo) {
|
|||||||
verifyOverlappingDecompression();
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, obuf);
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
@ -713,7 +713,7 @@ void PackTos::unpack(OutputFile *fo) {
|
|||||||
fo->write(obuf, ph.u_len - FH_SIZE); // orig. text+data+relocs
|
fo->write(obuf, ph.u_len - FH_SIZE); // orig. text+data+relocs
|
||||||
|
|
||||||
// copy any overlay
|
// copy any overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, obuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -176,7 +176,7 @@ void PackWcle::encodeEntryTable()
|
|||||||
//if (Opt_debug) printf("%d entries encoded.\n",n);
|
//if (Opt_debug) printf("%d entries encoded.\n",n);
|
||||||
UNUSED(n);
|
UNUSED(n);
|
||||||
|
|
||||||
soentries = ptr_diff(p, ientries) + 1;
|
soentries = ptr_udiff_bytes(p, ientries) + 1;
|
||||||
oentries = ientries;
|
oentries = ientries;
|
||||||
ientries = nullptr;
|
ientries = nullptr;
|
||||||
}
|
}
|
||||||
@ -290,12 +290,13 @@ void PackWcle::preprocessFixups()
|
|||||||
throwCantPack("files without relocations are not supported");
|
throwCantPack("files without relocations are not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteArray(rl, jc);
|
MemBuffer rl_membuf(jc);
|
||||||
ByteArray(srf, counts[objects+0]+1);
|
ByteArray(srf, counts[objects+0]+1);
|
||||||
ByteArray(slf, counts[objects+1]+1);
|
ByteArray(slf, counts[objects+1]+1);
|
||||||
|
|
||||||
upx_byte *selector_fixups = srf;
|
SPAN_S_VAR(upx_byte, rl, rl_membuf);
|
||||||
upx_byte *selfrel_fixups = slf;
|
SPAN_S_VAR(upx_byte, selector_fixups, srf_membuf);
|
||||||
|
SPAN_S_VAR(upx_byte, selfrel_fixups, slf_membuf);
|
||||||
unsigned rc = 0;
|
unsigned rc = 0;
|
||||||
|
|
||||||
upx_byte *fix = ifixups;
|
upx_byte *fix = ifixups;
|
||||||
@ -399,20 +400,20 @@ void PackWcle::preprocessFixups()
|
|||||||
delete[] ifixups;
|
delete[] ifixups;
|
||||||
ifixups = new upx_byte[1000];
|
ifixups = new upx_byte[1000];
|
||||||
}
|
}
|
||||||
fix = optimizeReloc32 (rl,rc,ifixups,iimage,file_size,1,&big_relocs);
|
fix = ifixups + optimizeReloc32 (rl,rc,ifixups,iimage,file_size,1,&big_relocs);
|
||||||
has_extra_code = srf != selector_fixups;
|
has_extra_code = ptr_udiff_bytes(selector_fixups, srf) != 0;
|
||||||
// FIXME: this could be removed if has_extra_code = false
|
// FIXME: this could be removed if has_extra_code = false
|
||||||
// but then we'll need a flag
|
// but then we'll need a flag
|
||||||
*selector_fixups++ = 0xC3; // ret
|
*selector_fixups++ = 0xC3; // ret
|
||||||
memcpy(fix,srf,selector_fixups-srf); // copy selector fixup code
|
memcpy(fix,srf,ptr_udiff_bytes(selector_fixups, srf)); // copy selector fixup code
|
||||||
fix += selector_fixups-srf;
|
fix += ptr_udiff_bytes(selector_fixups, srf);
|
||||||
|
|
||||||
memcpy(fix,slf,selfrel_fixups-slf); // copy self-relative fixup positions
|
memcpy(fix,slf,ptr_udiff_bytes(selfrel_fixups,slf)); // copy self-relative fixup positions
|
||||||
fix += selfrel_fixups-slf;
|
fix += ptr_udiff_bytes(selfrel_fixups, slf);
|
||||||
set_le32(fix,0xFFFFFFFFUL);
|
set_le32(fix,0xFFFFFFFFUL);
|
||||||
fix += 4;
|
fix += 4;
|
||||||
|
|
||||||
sofixups = ptr_diff(fix, ifixups);
|
sofixups = ptr_udiff(fix, ifixups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -427,7 +428,8 @@ void PackWcle::encodeImage(Filter *ft)
|
|||||||
|
|
||||||
delete[] ifixups; ifixups = nullptr;
|
delete[] ifixups; ifixups = nullptr;
|
||||||
|
|
||||||
oimage.allocForCompression(isize, RESERVED+512);
|
mb_oimage.allocForCompression(isize, RESERVED+512);
|
||||||
|
oimage = mb_oimage;
|
||||||
// prepare packheader
|
// prepare packheader
|
||||||
ph.u_len = isize;
|
ph.u_len = isize;
|
||||||
// prepare filter [already done]
|
// prepare filter [already done]
|
||||||
@ -435,7 +437,7 @@ void PackWcle::encodeImage(Filter *ft)
|
|||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
|
||||||
compressWithFilters(ibuf, isize,
|
compressWithFilters(ibuf, isize,
|
||||||
oimage + RESERVED,
|
raw_bytes(oimage + RESERVED, mb_oimage.getSize() - RESERVED),
|
||||||
ibuf + ft->addvalue, ft->buf_len,
|
ibuf + ft->addvalue, ft->buf_len,
|
||||||
nullptr, 0,
|
nullptr, 0,
|
||||||
ft, 512, &cconf, 0);
|
ft, 512, &cconf, 0);
|
||||||
@ -473,7 +475,7 @@ void PackWcle::pack(OutputFile *fo)
|
|||||||
readNonResidentNames();
|
readNonResidentNames();
|
||||||
|
|
||||||
// if (find_le32(iimage,20,get_le32("UPX ")) >= 0)
|
// if (find_le32(iimage,20,get_le32("UPX ")) >= 0)
|
||||||
if (find_le32(iimage,UPX_MIN(soimage,256u),UPX_MAGIC_LE32) >= 0)
|
if (find_le32(raw_bytes(iimage, soimage) ,UPX_MIN(soimage,256u),UPX_MAGIC_LE32) >= 0)
|
||||||
throwAlreadyPacked();
|
throwAlreadyPacked();
|
||||||
|
|
||||||
if (ih.init_ss_object != objects)
|
if (ih.init_ss_object != objects)
|
||||||
@ -556,14 +558,14 @@ void PackWcle::pack(OutputFile *fo)
|
|||||||
writeFile(fo, opt->watcom_le.le);
|
writeFile(fo, opt->watcom_le.le);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
verifyOverlappingDecompression(oimage + e_len, oimage.getSize() - e_len);
|
verifyOverlappingDecompression(mb_oimage + e_len, mb_oimage.getSize() - e_len);
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
||||||
+ getImageSize();
|
+ getImageSize();
|
||||||
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
||||||
checkOverlay(overlay);
|
checkOverlay(overlay);
|
||||||
copyOverlay(fo, overlay, &oimage);
|
copyOverlay(fo, overlay, mb_oimage);
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
@ -577,12 +579,14 @@ void PackWcle::pack(OutputFile *fo)
|
|||||||
|
|
||||||
void PackWcle::decodeFixups()
|
void PackWcle::decodeFixups()
|
||||||
{
|
{
|
||||||
upx_byte *p = oimage + soimage;
|
SPAN_P_VAR(upx_byte, p, oimage + soimage);
|
||||||
|
// assert(p.raw_size_in_bytes() == mb_oimage.getSize()); // Span sanity check
|
||||||
|
|
||||||
iimage.dealloc();
|
mb_iimage.dealloc();
|
||||||
|
iimage = nullptr;
|
||||||
|
|
||||||
MemBuffer tmpbuf;
|
MemBuffer tmpbuf;
|
||||||
unsigned const fixupn = unoptimizeReloc32(&p,oimage,&tmpbuf,1);
|
unsigned const fixupn = unoptimizeReloc32(p,oimage,tmpbuf,true);
|
||||||
|
|
||||||
MemBuffer wrkmem(8*fixupn+8);
|
MemBuffer wrkmem(8*fixupn+8);
|
||||||
unsigned ic,jc,o,r;
|
unsigned ic,jc,o,r;
|
||||||
@ -600,10 +604,10 @@ void PackWcle::decodeFixups()
|
|||||||
tmpbuf.dealloc();
|
tmpbuf.dealloc();
|
||||||
|
|
||||||
// selector fixups then self-relative fixups
|
// selector fixups then self-relative fixups
|
||||||
const upx_byte *selector_fixups = p;
|
SPAN_P_VAR(const upx_byte, selector_fixups, p);
|
||||||
|
|
||||||
// Find selfrel_fixups by skipping over selector_fixups.
|
// Find selfrel_fixups by skipping over selector_fixups.
|
||||||
const upx_byte *q = selector_fixups;
|
SPAN_P_VAR(const upx_byte, q, selector_fixups);
|
||||||
// The code is a subroutine that ends in RET (0xC3).
|
// The code is a subroutine that ends in RET (0xC3).
|
||||||
while (*q != 0xC3) {
|
while (*q != 0xC3) {
|
||||||
// Defend against tampered selector_fixups; see PackWcle::preprocessFixups().
|
// Defend against tampered selector_fixups; see PackWcle::preprocessFixups().
|
||||||
@ -622,20 +626,21 @@ void PackWcle::decodeFixups()
|
|||||||
}
|
}
|
||||||
// Guard against run-away.
|
// Guard against run-away.
|
||||||
static unsigned char const blank[9] = {0};
|
static unsigned char const blank[9] = {0};
|
||||||
if (q > (oimage + ph.u_len - sizeof(blank)) // catastrophic worst case
|
if (ptr_diff_bytes(oimage + ph.u_len - sizeof(blank), raw_bytes(q,0)) < 0 // catastrophic worst case
|
||||||
|| !memcmp(blank, q, sizeof(blank)) // no-good early warning
|
|| !memcmp(blank, q, sizeof(blank)) // no-good early warning
|
||||||
) {
|
) {
|
||||||
char msg[50]; snprintf(msg, sizeof(msg),
|
char msg[50]; snprintf(msg, sizeof(msg),
|
||||||
"bad selector_fixups +%#zx", q - selector_fixups);
|
"bad selector_fixups %d", ptr_diff_bytes(q, selector_fixups));
|
||||||
throwCantPack(msg);
|
throwCantPack(msg);
|
||||||
}
|
}
|
||||||
q += 9;
|
q += 9;
|
||||||
}
|
}
|
||||||
unsigned selectlen = ptr_diff(q, selector_fixups)/9;
|
unsigned selectlen = ptr_udiff_bytes(q, selector_fixups)/9;
|
||||||
const upx_byte *selfrel_fixups = 1+ q; // Skip the 0xC3
|
SPAN_P_VAR(const upx_byte, selfrel_fixups, q + 1); // Skip the 0xC3
|
||||||
|
|
||||||
ofixups = New(upx_byte, fixupn*9+1000+selectlen*5);
|
const unsigned fbytes = fixupn*9+1000+selectlen*5;
|
||||||
upx_bytep fp = ofixups;
|
ofixups = New(upx_byte, fbytes);
|
||||||
|
SPAN_S_VAR(upx_byte, fp, ofixups, fbytes, ofixups);
|
||||||
|
|
||||||
for (ic = 1, jc = 0; ic <= opages; ic++)
|
for (ic = 1, jc = 0; ic <= opages; ic++)
|
||||||
{
|
{
|
||||||
@ -698,11 +703,11 @@ void PackWcle::decodeFixups()
|
|||||||
fp += fp[1] ? 9 : 7;
|
fp += fp[1] ? 9 : 7;
|
||||||
jc += 2;
|
jc += 2;
|
||||||
}
|
}
|
||||||
set_le32(ofpage_table+ic,ptr_diff(fp,ofixups));
|
set_le32(ofpage_table+ic,ptr_udiff_bytes(fp,ofixups));
|
||||||
}
|
}
|
||||||
for (ic=0; ic < FIXUP_EXTRA; ic++)
|
for (ic=0; ic < FIXUP_EXTRA; ic++)
|
||||||
*fp++ = 0;
|
*fp++ = 0;
|
||||||
sofixups = ptr_diff(fp, ofixups);
|
sofixups = ptr_udiff_bytes(fp, ofixups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -751,7 +756,8 @@ void PackWcle::decodeObjectTable()
|
|||||||
|
|
||||||
void PackWcle::decodeImage()
|
void PackWcle::decodeImage()
|
||||||
{
|
{
|
||||||
oimage.allocForUncompression(ph.u_len);
|
mb_oimage.allocForUncompression(ph.u_len);
|
||||||
|
oimage = mb_oimage;
|
||||||
|
|
||||||
decompress(iimage + ph.buf_offset + ph.getPackHeaderSize(),oimage);
|
decompress(iimage + ph.buf_offset + ph.getPackHeaderSize(),oimage);
|
||||||
soimage = get_le32(oimage + ph.u_len - 5);
|
soimage = get_le32(oimage + ph.u_len - 5);
|
||||||
@ -762,11 +768,13 @@ void PackWcle::decodeImage()
|
|||||||
|
|
||||||
void PackWcle::decodeEntryTable()
|
void PackWcle::decodeEntryTable()
|
||||||
{
|
{
|
||||||
unsigned count,object,r;
|
unsigned count,object,n,r;
|
||||||
upx_byte *p = ientries;
|
SPAN_S_VAR(upx_byte, p, ientries, soentries);
|
||||||
|
n = 0;
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
count = *p;
|
count = *p;
|
||||||
|
n += count;
|
||||||
if (p[1] == 0) // unused bundle
|
if (p[1] == 0) // unused bundle
|
||||||
p += 2;
|
p += 2;
|
||||||
else if (p[1] == 3) // 32-bit offset bundle
|
else if (p[1] == 3) // 32-bit offset bundle
|
||||||
@ -787,8 +795,9 @@ void PackWcle::decodeEntryTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if (Opt_debug) printf("\n%d entries decoded.\n",n);
|
//if (Opt_debug) printf("\n%d entries decoded.\n",n);
|
||||||
|
UNUSED(n);
|
||||||
|
|
||||||
soentries = ptr_diff(p, ientries) + 1;
|
soentries = ptr_udiff_bytes(p, ientries) + 1;
|
||||||
oentries = ientries;
|
oentries = ientries;
|
||||||
ientries = nullptr;
|
ientries = nullptr;
|
||||||
}
|
}
|
||||||
@ -852,7 +861,7 @@ void PackWcle::unpack(OutputFile *fo)
|
|||||||
ft.cto = (unsigned char) ph.filter_cto;
|
ft.cto = (unsigned char) ph.filter_cto;
|
||||||
if (ph.version < 11)
|
if (ph.version < 11)
|
||||||
ft.cto = (unsigned char) (get_le32(oimage+ph.u_len-9) >> 24);
|
ft.cto = (unsigned char) (get_le32(oimage+ph.u_len-9) >> 24);
|
||||||
ft.unfilter(oimage+text_vaddr, text_size);
|
ft.unfilter(raw_bytes(oimage+text_vaddr, text_size), text_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
decodeFixupPageTable();
|
decodeFixupPageTable();
|
||||||
@ -878,7 +887,7 @@ void PackWcle::unpack(OutputFile *fo)
|
|||||||
+ getImageSize();
|
+ getImageSize();
|
||||||
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
||||||
checkOverlay(overlay);
|
checkOverlay(overlay);
|
||||||
copyOverlay(fo, overlay, &oimage);
|
copyOverlay(fo, overlay, mb_oimage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|||||||
107
src/packer.cpp
107
src/packer.cpp
@ -180,7 +180,7 @@ int forced_method(int method) // extract the forced method
|
|||||||
// compress - wrap call to low-level upx_compress()
|
// compress - wrap call to low-level upx_compress()
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
bool Packer::compress(SPAN_P(upx_byte) i_ptr, unsigned i_len, SPAN_P(upx_byte) o_ptr,
|
||||||
const upx_compress_config_t *cconf_parm) {
|
const upx_compress_config_t *cconf_parm) {
|
||||||
ph.u_len = i_len;
|
ph.u_len = i_len;
|
||||||
ph.c_len = 0;
|
ph.c_len = 0;
|
||||||
@ -194,7 +194,7 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
|||||||
ph.saved_u_adler = ph.u_adler;
|
ph.saved_u_adler = ph.u_adler;
|
||||||
ph.saved_c_adler = ph.c_adler;
|
ph.saved_c_adler = ph.c_adler;
|
||||||
// update checksum of uncompressed data
|
// update checksum of uncompressed data
|
||||||
ph.u_adler = upx_adler32(i_ptr, ph.u_len, ph.u_adler);
|
ph.u_adler = upx_adler32(raw_bytes(i_ptr, ph.u_len), ph.u_len, ph.u_adler);
|
||||||
|
|
||||||
// set compression parameters
|
// set compression parameters
|
||||||
upx_compress_config_t cconf;
|
upx_compress_config_t cconf;
|
||||||
@ -241,8 +241,8 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
|||||||
// OutputFile::dump("data.raw", in, ph.u_len);
|
// OutputFile::dump("data.raw", in, ph.u_len);
|
||||||
|
|
||||||
// compress
|
// compress
|
||||||
int r = upx_compress(i_ptr, ph.u_len, o_ptr, &ph.c_len, uip->getCallback(), method, ph.level,
|
int r = upx_compress(raw_bytes(i_ptr, ph.u_len), ph.u_len, raw_bytes(o_ptr, 0), &ph.c_len,
|
||||||
&cconf, &ph.compress_result);
|
uip->getCallback(), method, ph.level, &cconf, &ph.compress_result);
|
||||||
|
|
||||||
// uip->finalCallback(ph.u_len, ph.c_len);
|
// uip->finalCallback(ph.u_len, ph.c_len);
|
||||||
uip->endCallback();
|
uip->endCallback();
|
||||||
@ -277,12 +277,13 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// update checksum of compressed data
|
// update checksum of compressed data
|
||||||
ph.c_adler = upx_adler32(o_ptr, ph.c_len, ph.c_adler);
|
ph.c_adler = upx_adler32(raw_bytes(o_ptr, ph.c_len), ph.c_len, ph.c_adler);
|
||||||
// Decompress and verify. Skip this when using the fastest level.
|
// Decompress and verify. Skip this when using the fastest level.
|
||||||
if (!ph_skipVerify(ph)) {
|
if (!ph_skipVerify(ph)) {
|
||||||
// decompress
|
// decompress
|
||||||
unsigned new_len = ph.u_len;
|
unsigned new_len = ph.u_len;
|
||||||
r = upx_decompress(o_ptr, ph.c_len, i_ptr, &new_len, method, &ph.compress_result);
|
r = upx_decompress(raw_bytes(o_ptr, ph.c_len), ph.c_len, raw_bytes(i_ptr, ph.u_len),
|
||||||
|
&new_len, method, &ph.compress_result);
|
||||||
if (r == UPX_E_OUT_OF_MEMORY)
|
if (r == UPX_E_OUT_OF_MEMORY)
|
||||||
throwOutOfMemoryException();
|
throwOutOfMemoryException();
|
||||||
// printf("%d %d: %d %d %d\n", method, r, ph.c_len, ph.u_len, new_len);
|
// printf("%d %d: %d %d %d\n", method, r, ph.c_len, ph.u_len, new_len);
|
||||||
@ -292,7 +293,7 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
|||||||
throwInternalError("decompression failed (size error)");
|
throwInternalError("decompression failed (size error)");
|
||||||
|
|
||||||
// verify decompression
|
// verify decompression
|
||||||
if (ph.u_adler != upx_adler32(i_ptr, ph.u_len, ph.saved_u_adler))
|
if (ph.u_adler != upx_adler32(raw_bytes(i_ptr, ph.u_len), ph.u_len, ph.saved_u_adler))
|
||||||
throwInternalError("decompression failed (checksum error)");
|
throwInternalError("decompression failed (checksum error)");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -340,13 +341,13 @@ bool Packer::checkFinalCompressionRatio(const OutputFile *fo) const {
|
|||||||
// decompress
|
// decompress
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verify_checksum,
|
void ph_decompress(PackHeader &ph, SPAN_P(const upx_byte) in, SPAN_P(upx_byte) out,
|
||||||
Filter *ft) {
|
bool verify_checksum, Filter *ft) {
|
||||||
unsigned adler;
|
unsigned adler;
|
||||||
|
|
||||||
// verify checksum of compressed data
|
// verify checksum of compressed data
|
||||||
if (verify_checksum) {
|
if (verify_checksum) {
|
||||||
adler = upx_adler32(in, ph.c_len, ph.saved_c_adler);
|
adler = upx_adler32(raw_bytes(in, ph.c_len), ph.c_len, ph.saved_c_adler);
|
||||||
if (adler != ph.c_adler)
|
if (adler != ph.c_adler)
|
||||||
throwChecksumError();
|
throwChecksumError();
|
||||||
}
|
}
|
||||||
@ -356,8 +357,8 @@ void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verif
|
|||||||
throwCantUnpack("header corrupted");
|
throwCantUnpack("header corrupted");
|
||||||
}
|
}
|
||||||
unsigned new_len = ph.u_len;
|
unsigned new_len = ph.u_len;
|
||||||
int r =
|
int r = upx_decompress(raw_bytes(in, ph.c_len), ph.c_len, raw_bytes(out, ph.u_len), &new_len,
|
||||||
upx_decompress(in, ph.c_len, out, &new_len, forced_method(ph.method), &ph.compress_result);
|
forced_method(ph.method), &ph.compress_result);
|
||||||
if (r == UPX_E_OUT_OF_MEMORY)
|
if (r == UPX_E_OUT_OF_MEMORY)
|
||||||
throwOutOfMemoryException();
|
throwOutOfMemoryException();
|
||||||
if (r != UPX_E_OK || new_len != ph.u_len)
|
if (r != UPX_E_OK || new_len != ph.u_len)
|
||||||
@ -366,14 +367,15 @@ void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verif
|
|||||||
// verify checksum of decompressed data
|
// verify checksum of decompressed data
|
||||||
if (verify_checksum) {
|
if (verify_checksum) {
|
||||||
if (ft)
|
if (ft)
|
||||||
ft->unfilter(out, ph.u_len);
|
ft->unfilter(raw_bytes(out, ph.u_len), ph.u_len);
|
||||||
adler = upx_adler32(out, ph.u_len, ph.saved_u_adler);
|
adler = upx_adler32(raw_bytes(out, ph.u_len), ph.u_len, ph.saved_u_adler);
|
||||||
if (adler != ph.u_adler)
|
if (adler != ph.u_adler)
|
||||||
throwChecksumError();
|
throwChecksumError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packer::decompress(const upx_bytep in, upx_bytep out, bool verify_checksum, Filter *ft) {
|
void Packer::decompress(SPAN_P(const upx_byte) in, SPAN_P(upx_byte) out, bool verify_checksum,
|
||||||
|
Filter *ft) {
|
||||||
ph_decompress(ph, in, out, verify_checksum, ft);
|
ph_decompress(ph, in, out, verify_checksum, ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,10 +537,10 @@ void Packer::checkOverlay(unsigned overlay) {
|
|||||||
throw OverlayException("file has overlay -- skipped; try '--overlay=copy'");
|
throw OverlayException("file has overlay -- skipped; try '--overlay=copy'");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool do_seek) {
|
void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer &buf, bool do_seek) {
|
||||||
assert((int) overlay >= 0);
|
assert((int) overlay >= 0);
|
||||||
assert(overlay < file_size_u);
|
assert(overlay < file_size_u);
|
||||||
buf->checkState();
|
buf.checkState();
|
||||||
if (!fo || overlay == 0)
|
if (!fo || overlay == 0)
|
||||||
return;
|
return;
|
||||||
if (opt->overlay != opt->COPY_OVERLAY) {
|
if (opt->overlay != opt->COPY_OVERLAY) {
|
||||||
@ -551,7 +553,7 @@ void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool
|
|||||||
fi->seek(-(upx_off_t) overlay, SEEK_END);
|
fi->seek(-(upx_off_t) overlay, SEEK_END);
|
||||||
|
|
||||||
// get buffer size, align to improve i/o speed
|
// get buffer size, align to improve i/o speed
|
||||||
unsigned buf_size = buf->getSize();
|
unsigned buf_size = buf.getSize();
|
||||||
if (buf_size > 65536)
|
if (buf_size > 65536)
|
||||||
buf_size = ALIGN_DOWN(buf_size, 4096u);
|
buf_size = ALIGN_DOWN(buf_size, 4096u);
|
||||||
assert((int) buf_size > 0);
|
assert((int) buf_size > 0);
|
||||||
@ -562,7 +564,7 @@ void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool
|
|||||||
fo->write(buf, len);
|
fo->write(buf, len);
|
||||||
overlay -= len;
|
overlay -= len;
|
||||||
} while (overlay > 0);
|
} while (overlay > 0);
|
||||||
buf->checkState();
|
buf.checkState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a pseudo-unique program id.
|
// Create a pseudo-unique program id.
|
||||||
@ -643,14 +645,15 @@ int Packer::patchPackHeader(void *b, int blen) {
|
|||||||
int boff = find_le32(b, blen, UPX_MAGIC_LE32);
|
int boff = find_le32(b, blen, UPX_MAGIC_LE32);
|
||||||
checkPatch(b, blen, boff, size);
|
checkPatch(b, blen, boff, size);
|
||||||
|
|
||||||
unsigned char *p = (unsigned char *) b + boff;
|
auto bb = (upx_byte *) b;
|
||||||
ph.putPackHeader(p);
|
ph.putPackHeader(SPAN_S_MAKE(upx_byte, bb + boff, blen, bb));
|
||||||
|
|
||||||
return boff;
|
return boff;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Packer::getPackHeader(void const *b, int blen, bool allow_incompressible) {
|
bool Packer::getPackHeader(const void *b, int blen, bool allow_incompressible) {
|
||||||
if (!ph.fillPackHeader((unsigned char const *) b, blen))
|
auto bb = (const upx_byte *) b;
|
||||||
|
if (!ph.fillPackHeader(SPAN_S_MAKE(const upx_byte, bb, blen), blen))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ph.version > getVersion())
|
if (ph.version > getVersion())
|
||||||
@ -825,18 +828,19 @@ int Packer::patch_le32(void *b, int blen, const void *old, unsigned new_) {
|
|||||||
// relocation util
|
// relocation util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image,
|
unsigned Packer::optimizeReloc(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
|
||||||
unsigned headway, int bswap, int *big, int bits) {
|
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big,
|
||||||
|
int bits) {
|
||||||
if (opt->exact)
|
if (opt->exact)
|
||||||
throwCantPackExact();
|
throwCantPackExact();
|
||||||
|
|
||||||
*big = 0;
|
*big = 0;
|
||||||
if (relocnum == 0)
|
if (relocnum == 0)
|
||||||
return out;
|
return 0;
|
||||||
qsort(in, relocnum, 4, le32_compare);
|
qsort(raw_bytes(in, 4 * relocnum), relocnum, 4, le32_compare);
|
||||||
|
|
||||||
unsigned jc, pc, oc;
|
unsigned jc, pc, oc;
|
||||||
upx_byte *fix = out;
|
SPAN_P_VAR(upx_byte, fix, out);
|
||||||
|
|
||||||
pc = (unsigned) -4;
|
pc = (unsigned) -4;
|
||||||
for (jc = 0; jc < relocnum; jc++) {
|
for (jc = 0; jc < relocnum; jc++) {
|
||||||
@ -875,36 +879,35 @@ upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*fix++ = 0;
|
*fix++ = 0;
|
||||||
return fix;
|
return ptr_udiff_bytes(fix, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_byte *Packer::optimizeReloc32(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image,
|
unsigned Packer::optimizeReloc32(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
|
||||||
unsigned headway, int bswap, int *big) {
|
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big) {
|
||||||
return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 32);
|
return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_byte *Packer::optimizeReloc64(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image,
|
unsigned Packer::optimizeReloc64(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
|
||||||
unsigned headway, int bswap, int *big) {
|
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big) {
|
||||||
return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 64);
|
return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Packer::unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out, int bswap,
|
unsigned Packer::unoptimizeReloc(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
|
||||||
int bits) {
|
bool bswap, int bits) {
|
||||||
upx_byte *p;
|
SPAN_P_VAR(upx_byte, p, in);
|
||||||
unsigned relocn = 0;
|
unsigned relocn = 0;
|
||||||
for (p = *in; *p; p++, relocn++)
|
for (; *p; p++, relocn++)
|
||||||
if (*p >= 0xF0) {
|
if (*p >= 0xF0) {
|
||||||
if (*p == 0xF0 && get_le16(p + 1) == 0)
|
if (*p == 0xF0 && get_le16(p + 1) == 0)
|
||||||
p += 4;
|
p += 4;
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
upx_byte const *in_end = p;
|
SPAN_P_VAR(upx_byte, const in_end, p);
|
||||||
// fprintf(stderr,"relocnum=%x\n",relocn);
|
// fprintf(stderr,"relocnum=%x\n",relocn);
|
||||||
out->alloc(4 * relocn + 4); // one extra data
|
out.alloc(4 * (relocn + 1)); // one extra entry
|
||||||
LE32 *const outp = (LE32 *) (unsigned char *) *out;
|
SPAN_S_VAR(LE32, relocs, out);
|
||||||
LE32 *relocs = outp;
|
|
||||||
unsigned jc = (unsigned) -4;
|
unsigned jc = (unsigned) -4;
|
||||||
for (p = *in; p < in_end; p++) {
|
for (p = in; p < in_end; p++) {
|
||||||
if (*p < 0xF0)
|
if (*p < 0xF0)
|
||||||
jc += *p;
|
jc += *p;
|
||||||
else {
|
else {
|
||||||
@ -920,32 +923,34 @@ unsigned Packer::unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out,
|
|||||||
if (!relocn--) {
|
if (!relocn--) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (bswap && image) {
|
if (bswap && image != nullptr) {
|
||||||
if (bits == 32) {
|
if (bits == 32) {
|
||||||
set_be32(image + jc, get_le32(image + jc));
|
set_be32(image + jc, get_le32(image + jc));
|
||||||
if ((size_t)(p - (image + jc)) < 4) {
|
if ((unsigned) ptr_diff_bytes(p, image + jc) < 4) {
|
||||||
// data must not overlap control
|
// data must not overlap control
|
||||||
p = (4 - 1) + image + jc; // -1: 'for' also increments
|
p = image + jc + (4 - 1); // -1: 'for' also increments
|
||||||
}
|
}
|
||||||
} else if (bits == 64) {
|
} else if (bits == 64) {
|
||||||
set_be64(image + jc, get_le64(image + jc));
|
set_be64(image + jc, get_le64(image + jc));
|
||||||
if ((size_t)(p - (image + jc)) < 8) {
|
if ((unsigned) ptr_diff_bytes(p, image + jc) < 8) {
|
||||||
// data must not overlap control
|
// data must not overlap control
|
||||||
p = (8 - 1) + image + jc; // -1: 'for' also increments
|
p = image + jc + (8 - 1); // -1: 'for' also increments
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
throwInternalError("unoptimizeReloc problem");
|
throwInternalError("unoptimizeReloc problem");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*in = p + 1;
|
in = p + 1;
|
||||||
return (unsigned) (relocs - outp);
|
return ptr_udiff_bytes(relocs, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Packer::unoptimizeReloc32(upx_byte **in, upx_byte *image, MemBuffer *out, int bswap) {
|
unsigned Packer::unoptimizeReloc32(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
|
||||||
|
bool bswap) {
|
||||||
return unoptimizeReloc(in, image, out, bswap, 32);
|
return unoptimizeReloc(in, image, out, bswap, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Packer::unoptimizeReloc64(upx_byte **in, upx_byte *image, MemBuffer *out, int bswap) {
|
unsigned Packer::unoptimizeReloc64(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
|
||||||
|
bool bswap) {
|
||||||
return unoptimizeReloc(in, image, out, bswap, 64);
|
return unoptimizeReloc(in, image, out, bswap, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
72
src/packer.h
72
src/packer.h
@ -25,10 +25,11 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UPX_PACKER_H
|
#pragma once
|
||||||
#define __UPX_PACKER_H 1
|
#ifndef UPX_PACKER_H__
|
||||||
|
#define UPX_PACKER_H__ 1
|
||||||
|
|
||||||
#include "mem.h"
|
#include "util/membuffer.h"
|
||||||
|
|
||||||
class InputFile;
|
class InputFile;
|
||||||
class OutputFile;
|
class OutputFile;
|
||||||
@ -42,15 +43,14 @@ class Filter;
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
// see stub/src/include/header.S
|
// see stub/src/include/header.S
|
||||||
class PackHeader {
|
class PackHeader final {
|
||||||
friend class Packer;
|
friend class Packer;
|
||||||
|
|
||||||
private:
|
// these are strictly private to friend Packer
|
||||||
// these are strictly private to Packer and not accessible in subclasses
|
|
||||||
PackHeader();
|
PackHeader();
|
||||||
|
|
||||||
void putPackHeader(upx_bytep p);
|
void putPackHeader(SPAN_S(upx_byte) p);
|
||||||
bool fillPackHeader(const upx_bytep b, int blen);
|
bool fillPackHeader(SPAN_S(const upx_byte) b, int blen);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int getPackHeaderSize() const;
|
int getPackHeaderSize() const;
|
||||||
@ -95,9 +95,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool ph_skipVerify(const PackHeader &ph);
|
bool ph_skipVerify(const PackHeader &ph);
|
||||||
void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verify_checksum,
|
void ph_decompress(PackHeader &ph, SPAN_P(const upx_byte) in, SPAN_P(upx_byte) out,
|
||||||
Filter *ft);
|
bool verify_checksum, Filter *ft);
|
||||||
bool ph_testOverlappingDecompression(const PackHeader &ph, const upx_bytep buf,
|
bool ph_testOverlappingDecompression(const PackHeader &ph, SPAN_P(const upx_byte) buf,
|
||||||
unsigned overlap_overhead);
|
unsigned overlap_overhead);
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -107,7 +107,6 @@ bool ph_testOverlappingDecompression(const PackHeader &ph, const upx_bytep buf,
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class Packer {
|
class Packer {
|
||||||
// friend class PackMaster;
|
|
||||||
friend class UiPacker;
|
friend class UiPacker;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -163,10 +162,10 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
// main compression drivers
|
// main compression drivers
|
||||||
virtual bool compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
bool compress(SPAN_P(upx_byte) i_ptr, unsigned i_len, SPAN_P(upx_byte) o_ptr,
|
||||||
const upx_compress_config_t *cconf = nullptr);
|
const upx_compress_config_t *cconf = nullptr);
|
||||||
virtual void decompress(const upx_bytep in, upx_bytep out, bool verify_checksum = true,
|
void decompress(SPAN_P(const upx_byte) in, SPAN_P(upx_byte) out, bool verify_checksum = true,
|
||||||
Filter *ft = nullptr);
|
Filter *ft = nullptr);
|
||||||
virtual bool checkDefaultCompressionRatio(unsigned u_len, unsigned c_len) const;
|
virtual bool checkDefaultCompressionRatio(unsigned u_len, unsigned c_len) const;
|
||||||
virtual bool checkCompressionRatio(unsigned u_len, unsigned c_len) const;
|
virtual bool checkCompressionRatio(unsigned u_len, unsigned c_len) const;
|
||||||
virtual bool checkFinalCompressionRatio(const OutputFile *fo) const;
|
virtual bool checkFinalCompressionRatio(const OutputFile *fo) const;
|
||||||
@ -202,7 +201,7 @@ protected:
|
|||||||
|
|
||||||
// packheader handling
|
// packheader handling
|
||||||
virtual int patchPackHeader(void *b, int blen);
|
virtual int patchPackHeader(void *b, int blen);
|
||||||
virtual bool getPackHeader(void const *b, int blen, bool allow_incompressible = false);
|
virtual bool getPackHeader(const void *b, int blen, bool allow_incompressible = false);
|
||||||
virtual bool readPackHeader(int len, bool allow_incompressible = false);
|
virtual bool readPackHeader(int len, bool allow_incompressible = false);
|
||||||
virtual void checkAlreadyPacked(const void *b, int blen);
|
virtual void checkAlreadyPacked(const void *b, int blen);
|
||||||
|
|
||||||
@ -256,7 +255,7 @@ protected:
|
|||||||
// stub and overlay util
|
// stub and overlay util
|
||||||
static void handleStub(InputFile *fi, OutputFile *fo, unsigned size);
|
static void handleStub(InputFile *fi, OutputFile *fo, unsigned size);
|
||||||
virtual void checkOverlay(unsigned overlay);
|
virtual void checkOverlay(unsigned overlay);
|
||||||
virtual void copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool do_seek = true);
|
virtual void copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer &buf, bool do_seek = true);
|
||||||
|
|
||||||
// misc util
|
// misc util
|
||||||
virtual unsigned getRandomId() const;
|
virtual unsigned getRandomId() const;
|
||||||
@ -273,34 +272,37 @@ protected:
|
|||||||
void checkPatch(void *b, int blen, int boff, int size);
|
void checkPatch(void *b, int blen, int boff, int size);
|
||||||
|
|
||||||
// relocation util
|
// relocation util
|
||||||
static upx_byte *optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image,
|
static unsigned optimizeReloc(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
|
||||||
unsigned headway, int bs, int *big, int bits);
|
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big,
|
||||||
static unsigned unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out, int bs,
|
int bits);
|
||||||
int bits);
|
static unsigned unoptimizeReloc(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
|
||||||
|
bool bswap, int bits);
|
||||||
|
|
||||||
static upx_byte *optimizeReloc32(upx_byte *in, unsigned relocnum, upx_byte *out,
|
static unsigned optimizeReloc32(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
|
||||||
upx_byte *image, unsigned headway, int bs, int *big);
|
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big);
|
||||||
static unsigned unoptimizeReloc32(upx_byte **in, upx_byte *image, MemBuffer *out, int bs);
|
static unsigned unoptimizeReloc32(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
|
||||||
|
bool bswap);
|
||||||
|
|
||||||
static upx_byte *optimizeReloc64(upx_byte *in, unsigned relocnum, upx_byte *out,
|
static unsigned optimizeReloc64(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
|
||||||
upx_byte *image, unsigned headway, int bs, int *big);
|
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big);
|
||||||
static unsigned unoptimizeReloc64(upx_byte **in, upx_byte *image, MemBuffer *out, int bs);
|
static unsigned unoptimizeReloc64(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
|
||||||
|
bool bswap);
|
||||||
|
|
||||||
// target endianness abstraction
|
// Target Endianness abstraction
|
||||||
unsigned get_te16(const void *p) const { return bele->get16(p); }
|
unsigned get_te16(const void *p) const { return bele->get16(p); }
|
||||||
unsigned get_te32(const void *p) const { return bele->get32(p); }
|
unsigned get_te32(const void *p) const { return bele->get32(p); }
|
||||||
upx_uint64_t get_te64(const void *p) const { return bele->get64(p); }
|
upx_uint64_t get_te64(const void *p) const { return bele->get64(p); }
|
||||||
void set_te16(void *p, unsigned v) const { bele->set16(p, v); }
|
void set_te16(void *p, unsigned v) { bele->set16(p, v); }
|
||||||
void set_te32(void *p, unsigned v) const { bele->set32(p, v); }
|
void set_te32(void *p, unsigned v) { bele->set32(p, v); }
|
||||||
void set_te64(void *p, upx_uint64_t v) const { bele->set64(p, v); }
|
void set_te64(void *p, upx_uint64_t v) { bele->set64(p, v); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const N_BELE_RTP::AbstractPolicy *bele = nullptr; // target endianness
|
const N_BELE_RTP::AbstractPolicy *bele = nullptr; // target endianness
|
||||||
InputFile *fi = nullptr;
|
InputFile *fi = nullptr;
|
||||||
|
|
||||||
union { // unnamed union
|
union { // unnamed union
|
||||||
upx_int64_t file_size; // will get set by constructor
|
upx_int64_t file_size = 0; // will get set by constructor
|
||||||
upx_uint64_t file_size_u; // explicitly unsigned
|
upx_uint64_t file_size_u; // explicitly unsigned
|
||||||
};
|
};
|
||||||
|
|
||||||
PackHeader ph; // must be filled by canUnpack()
|
PackHeader ph; // must be filled by canUnpack()
|
||||||
|
|||||||
@ -41,7 +41,7 @@ PackHeader::PackHeader() : version(-1), format(-1) {}
|
|||||||
// simple checksum for the header itself (since version 10)
|
// simple checksum for the header itself (since version 10)
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static unsigned char get_packheader_checksum(const upx_bytep buf, int len) {
|
static unsigned char get_packheader_checksum(SPAN_S(const upx_byte) buf, int len) {
|
||||||
assert(len >= 4);
|
assert(len >= 4);
|
||||||
assert(get_le32(buf) == UPX_MAGIC_LE32);
|
assert(get_le32(buf) == UPX_MAGIC_LE32);
|
||||||
// printf("1 %d\n", len);
|
// printf("1 %d\n", len);
|
||||||
@ -92,7 +92,7 @@ int PackHeader::getPackHeaderSize() const {
|
|||||||
// see stub/header.ash
|
// see stub/header.ash
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void PackHeader::putPackHeader(upx_bytep p) {
|
void PackHeader::putPackHeader(SPAN_S(upx_byte) p) {
|
||||||
// NOTE: It is the caller's responsbility to ensure the buffer p has
|
// NOTE: It is the caller's responsbility to ensure the buffer p has
|
||||||
// sufficient space for the header.
|
// sufficient space for the header.
|
||||||
assert(get_le32(p) == UPX_MAGIC_LE32);
|
assert(get_le32(p) == UPX_MAGIC_LE32);
|
||||||
@ -170,12 +170,12 @@ void PackHeader::putPackHeader(upx_bytep p) {
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
bool PackHeader::fillPackHeader(SPAN_S(const upx_byte) buf, int blen) {
|
||||||
int boff = find_le32(buf, blen, UPX_MAGIC_LE32);
|
int boff = find_le32(raw_bytes(buf, blen), blen, UPX_MAGIC_LE32);
|
||||||
if (boff < 0)
|
if (boff < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const upx_bytep const p = buf + boff;
|
SPAN_S_VAR(const upx_byte, p, buf + boff);
|
||||||
unsigned const headway = blen - boff; // bytes remaining in buf
|
unsigned const headway = blen - boff; // bytes remaining in buf
|
||||||
|
|
||||||
if (headway < (1 + 7))
|
if (headway < (1 + 7))
|
||||||
|
|||||||
224
src/pefile.cpp
224
src/pefile.cpp
@ -39,42 +39,51 @@
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "bptr.h"
|
#include "util/bptr.h"
|
||||||
#define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
|
#if (WITH_SPAN >= 2) && 1
|
||||||
#define OPTR(type, var) BoundedPtr<type> var(obuf, obuf.getSize())
|
//#define IPTR(type, var) Span<type> var(ibuf, ibuf.getSize(), ibuf)
|
||||||
#define IPTR_I_D(type, var, disp) \
|
//#define OPTR(type, var) Span<type> var(obuf, obuf.getSize(), obuf)
|
||||||
BoundedPtr<type> var(ibuf + (disp), ibuf.getSize() - (disp), ibuf + (disp))
|
#define IPTR_I_D(type, var, disp) Span<type> var(ibuf + (disp), ibuf.getSize() - (disp), ibuf + (disp))
|
||||||
#define IPTR_I(type, var, v) BoundedPtr<type> var(ibuf, ibuf.getSize(), v)
|
#define IPTR_I(type, var, first) Span<type> var(first, ibuf)
|
||||||
#define OPTR_I(type, var, v) BoundedPtr<type> var(obuf, obuf.getSize(), v)
|
#define OPTR_I(type, var, first) Span<type> var(first, obuf)
|
||||||
#define IPTR_C(type, var, v) const BoundedPtr<type> var(ibuf, ibuf.getSize(), v)
|
#define IPTR_C(type, var, first) const Span<type> var(first, ibuf)
|
||||||
#define OPTR_C(type, var, v) const BoundedPtr<type> var(obuf, obuf.getSize(), v)
|
#define OPTR_C(type, var, first) const Span<type> var(first, obuf)
|
||||||
|
#else
|
||||||
|
//#define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
|
||||||
|
//#define OPTR(type, var) BoundedPtr<type> var(obuf, obuf.getSize())
|
||||||
|
#define IPTR_I_D(type, var, disp) BoundedPtr<type> var(ibuf + (disp), ibuf.getSize() - (disp), ibuf + (disp))
|
||||||
|
#define IPTR_I(type, var, first) BoundedPtr<type> var(ibuf, ibuf.getSize(), first)
|
||||||
|
#define OPTR_I(type, var, first) BoundedPtr<type> var(obuf, obuf.getSize(), first)
|
||||||
|
#define IPTR_C(type, var, first) const BoundedPtr<type> var(ibuf, ibuf.getSize(), first)
|
||||||
|
#define OPTR_C(type, var, first) const BoundedPtr<type> var(obuf, obuf.getSize(), first)
|
||||||
|
#endif
|
||||||
|
|
||||||
static void xcheck(const void *p)
|
static void xcheck(const void *p)
|
||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
throwCantUnpack("unexpected nullptr pointer; take care!");
|
throwCantUnpack("xcheck unexpected nullptr pointer; take care!");
|
||||||
}
|
}
|
||||||
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
|
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
|
||||||
{
|
{
|
||||||
const char *pp = (const char *) p;
|
const char *pp = (const char *) p;
|
||||||
const char *bb = (const char *) b;
|
const char *bb = (const char *) b;
|
||||||
if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
|
if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
|
||||||
throwCantUnpack("pointer out of range; take care!");
|
throwCantUnpack("xcheck pointer out of range; take care!");
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
|
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
|
||||||
{
|
{
|
||||||
ACC_UNUSED(b);
|
ACC_UNUSED(b);
|
||||||
if (poff > blen || poff + plen > blen)
|
if (poff > blen || poff + plen > blen)
|
||||||
throwCantUnpack("pointer out of range; take care!");
|
throwCantUnpack("xcheck pointer out of range; take care!");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#define ICHECK(x, size) xcheck(x, size, ibuf, ibuf.getSize())
|
#define ICHECK(x, size) xcheck(raw_bytes(x, 0), size, ibuf, ibuf.getSize())
|
||||||
#define OCHECK(x, size) xcheck(x, size, obuf, obuf.getSize())
|
#define OCHECK(x, size) xcheck(raw_bytes(x, 0), size, obuf, obuf.getSize())
|
||||||
|
|
||||||
#define imemset(a,b,c) ICHECK(a,c), memset(a,b,c)
|
//#define imemset(a,b,c) ICHECK(a,c), memset(a,b,c)
|
||||||
#define omemset(a,b,c) OCHECK(a,c), memset(a,b,c)
|
//#define omemset(a,b,c) OCHECK(a,c), memset(a,b,c)
|
||||||
#define imemcpy(a,b,c) ICHECK(a,c), memcpy(a,b,c)
|
//#define imemcpy(a,b,c) ICHECK(a,c), memcpy(a,b,c)
|
||||||
#define omemcpy(a,b,c) OCHECK(a,c), memcpy(a,b,c)
|
#define omemcpy(a,b,c) OCHECK(a,c), memcpy(a,b,c)
|
||||||
#define omemmove(a,b,c) OCHECK(a,c), memmove(a,b,c)
|
#define omemmove(a,b,c) OCHECK(a,c), memmove(a,b,c)
|
||||||
|
|
||||||
@ -211,12 +220,12 @@ PeFile::Interval::~Interval()
|
|||||||
|
|
||||||
void PeFile::Interval::add(const void *start,unsigned len)
|
void PeFile::Interval::add(const void *start,unsigned len)
|
||||||
{
|
{
|
||||||
add(ptr_diff(start,base),len);
|
add(ptr_diff_bytes(start,base),len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeFile::Interval::add(const void *start,const void *end)
|
void PeFile::Interval::add(const void *start,const void *end)
|
||||||
{
|
{
|
||||||
add(ptr_diff(start,base),ptr_diff(end,start));
|
add(ptr_diff_bytes(start,base),ptr_diff_bytes(end,start));
|
||||||
}
|
}
|
||||||
|
|
||||||
int __acc_cdecl_qsort PeFile::Interval::compare(const void *p1,const void *p2)
|
int __acc_cdecl_qsort PeFile::Interval::compare(const void *p1,const void *p2)
|
||||||
@ -306,7 +315,7 @@ PeFile::Reloc::Reloc(upx_byte *s,unsigned si) :
|
|||||||
PeFile::Reloc::Reloc(unsigned rnum) :
|
PeFile::Reloc::Reloc(unsigned rnum) :
|
||||||
start(nullptr), size(0), rel(nullptr), rel1(nullptr)
|
start(nullptr), size(0), rel(nullptr), rel1(nullptr)
|
||||||
{
|
{
|
||||||
start = new upx_byte[mem_size(4, rnum, 8192)];
|
start = new upx_byte[mem_size(4, rnum, 8192)]; // => oxrelocs
|
||||||
counts[0] = 0;
|
counts[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +323,7 @@ bool PeFile::Reloc::next(unsigned &pos,unsigned &type)
|
|||||||
{
|
{
|
||||||
if (!rel)
|
if (!rel)
|
||||||
newRelocPos(start);
|
newRelocPos(start);
|
||||||
if (ptr_diff(rel, start) >= (int) size) {
|
if (ptr_diff_bytes(rel, start) >= (int) size) {
|
||||||
rel = nullptr; // rewind
|
rel = nullptr; // rewind
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -322,7 +331,7 @@ bool PeFile::Reloc::next(unsigned &pos,unsigned &type)
|
|||||||
pos = rel->pagestart + (*rel1 & 0xfff);
|
pos = rel->pagestart + (*rel1 & 0xfff);
|
||||||
type = *rel1++ >> 12;
|
type = *rel1++ >> 12;
|
||||||
//printf("%x %d\n",pos,type);
|
//printf("%x %d\n",pos,type);
|
||||||
if (ptr_diff(rel1,rel) >= (int) rel->size)
|
if (ptr_diff_bytes(rel1,rel) >= (int) rel->size)
|
||||||
newRelocPos(rel1);
|
newRelocPos(rel1);
|
||||||
return type == 0 ? next(pos,type) : true;
|
return type == 0 ? next(pos,type) : true;
|
||||||
}
|
}
|
||||||
@ -347,14 +356,14 @@ void PeFile::Reloc::finish(upx_byte *&p,unsigned &siz)
|
|||||||
{
|
{
|
||||||
prev = pos;
|
prev = pos;
|
||||||
*rel1 = 0;
|
*rel1 = 0;
|
||||||
rel->size = ALIGN_UP(ptr_diff(rel1,rel), 4);
|
rel->size = ALIGN_UP(ptr_diff_bytes(rel1,rel), 4);
|
||||||
newRelocPos((char *)rel + rel->size);
|
newRelocPos((char *)rel + rel->size);
|
||||||
rel->pagestart = (pos >> 4) &~ 0xfff;
|
rel->pagestart = (pos >> 4) &~ 0xfff;
|
||||||
}
|
}
|
||||||
*rel1++ = (pos << 12) + ((pos >> 4) & 0xfff);
|
*rel1++ = (pos << 12) + ((pos >> 4) & 0xfff);
|
||||||
}
|
}
|
||||||
p = start;
|
p = start;
|
||||||
siz = ptr_diff(rel1,start) &~ 3;
|
siz = ptr_udiff_bytes(rel1,start) &~ 3;
|
||||||
siz -= 8;
|
siz -= 8;
|
||||||
// siz can be 0 in 64-bit mode // assert(siz > 0);
|
// siz can be 0 in 64-bit mode // assert(siz > 0);
|
||||||
start = nullptr; // safety
|
start = nullptr; // safety
|
||||||
@ -389,7 +398,7 @@ void PeFile32::processRelocs() // pass1
|
|||||||
ih.objects = tryremove(IDADDR(PEDIR_RELOC), ih.objects);
|
ih.objects = tryremove(IDADDR(PEDIR_RELOC), ih.objects);
|
||||||
}
|
}
|
||||||
mb_orelocs.alloc(1);
|
mb_orelocs.alloc(1);
|
||||||
orelocs = (upx_byte *)mb_orelocs.getVoidPtr();
|
orelocs = mb_orelocs;
|
||||||
sorelocs = 0;
|
sorelocs = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -439,10 +448,9 @@ void PeFile32::processRelocs() // pass1
|
|||||||
|
|
||||||
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
|
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
|
||||||
mb_orelocs.alloc(mem_size(4, rnum, 1024)); // 1024 - safety
|
mb_orelocs.alloc(mem_size(4, rnum, 1024)); // 1024 - safety
|
||||||
orelocs = (upx_byte *)mb_orelocs.getVoidPtr();
|
orelocs = mb_orelocs;
|
||||||
sorelocs = ptr_diff(optimizeReloc32((upx_byte*) fix[3], xcounts[3],
|
sorelocs = optimizeReloc32((upx_byte*) fix[3], xcounts[3],
|
||||||
orelocs, ibuf + rvamin, ibufgood - rvamin, 1, &big_relocs),
|
orelocs, ibuf + rvamin, ibufgood - rvamin, true, &big_relocs);
|
||||||
orelocs);
|
|
||||||
delete [] fix[3];
|
delete [] fix[3];
|
||||||
|
|
||||||
// Malware that hides behind UPX often has PE header info that is
|
// Malware that hides behind UPX often has PE header info that is
|
||||||
@ -492,7 +500,7 @@ void PeFile64::processRelocs() // pass1
|
|||||||
ih.objects = tryremove(IDADDR(PEDIR_RELOC), ih.objects);
|
ih.objects = tryremove(IDADDR(PEDIR_RELOC), ih.objects);
|
||||||
}
|
}
|
||||||
mb_orelocs.alloc(1);
|
mb_orelocs.alloc(1);
|
||||||
orelocs = (upx_byte *)mb_orelocs.getVoidPtr();
|
orelocs = mb_orelocs;
|
||||||
sorelocs = 0;
|
sorelocs = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -545,10 +553,9 @@ void PeFile64::processRelocs() // pass1
|
|||||||
|
|
||||||
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
|
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
|
||||||
mb_orelocs.alloc(mem_size(4, rnum, 1024)); // 1024 - safety
|
mb_orelocs.alloc(mem_size(4, rnum, 1024)); // 1024 - safety
|
||||||
orelocs = (upx_byte *)mb_orelocs.getVoidPtr();
|
orelocs = mb_orelocs;
|
||||||
sorelocs = ptr_diff(optimizeReloc64((upx_byte*) fix[10], xcounts[10],
|
sorelocs = optimizeReloc64((upx_byte*) fix[10], xcounts[10],
|
||||||
orelocs, ibuf + rvamin, ibufgood - rvamin, 1, &big_relocs),
|
orelocs, ibuf + rvamin, ibufgood - rvamin, true, &big_relocs);
|
||||||
orelocs);
|
|
||||||
|
|
||||||
for (ic = 15; ic; ic--)
|
for (ic = 15; ic; ic--)
|
||||||
delete [] fix[ic];
|
delete [] fix[ic];
|
||||||
@ -896,7 +903,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
|||||||
if (IDADDR(PEDIR_IMPORT))
|
if (IDADDR(PEDIR_IMPORT))
|
||||||
{
|
{
|
||||||
for (;; ++dllnum, ++im) {
|
for (;; ++dllnum, ++im) {
|
||||||
unsigned const skip2 = ptr_diff(im, ibuf);
|
unsigned const skip2 = ptr_diff_bytes(im, ibuf);
|
||||||
(void)ibuf.subref("bad import %#x", skip2, sizeof(*im));
|
(void)ibuf.subref("bad import %#x", skip2, sizeof(*im));
|
||||||
if (!im->dllname)
|
if (!im->dllname)
|
||||||
break;
|
break;
|
||||||
@ -975,8 +982,8 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mb_oimport.alloc(soimport);
|
mb_oimport.alloc(soimport);
|
||||||
oimport = (upx_byte *)mb_oimport.getVoidPtr();
|
mb_oimport.clear();
|
||||||
memset(oimport,0,soimport);
|
oimport = mb_oimport;
|
||||||
|
|
||||||
qsort(idlls,dllnum,sizeof (udll*),udll::compare);
|
qsort(idlls,dllnum,sizeof (udll*),udll::compare);
|
||||||
|
|
||||||
@ -1017,7 +1024,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
|||||||
Interval names(ibuf),iats(ibuf),lookups(ibuf);
|
Interval names(ibuf),iats(ibuf),lookups(ibuf);
|
||||||
|
|
||||||
// create the preprocessed data
|
// create the preprocessed data
|
||||||
upx_byte *ppi = oimport; // preprocessed imports
|
SPAN_P_VAR(upx_byte, ppi, oimport); // preprocessed imports
|
||||||
for (ic = 0; ic < dllnum; ic++)
|
for (ic = 0; ic < dllnum; ic++)
|
||||||
{
|
{
|
||||||
LEXX *tarr = idlls[ic]->lookupt;
|
LEXX *tarr = idlls[ic]->lookupt;
|
||||||
@ -1052,7 +1059,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
|||||||
}
|
}
|
||||||
ppi++;
|
ppi++;
|
||||||
|
|
||||||
unsigned esize = ptr_diff((char *)tarr, (char *)idlls[ic]->lookupt);
|
unsigned esize = ptr_diff_bytes(tarr, idlls[ic]->lookupt);
|
||||||
lookups.add(idlls[ic]->lookupt,esize);
|
lookups.add(idlls[ic]->lookupt,esize);
|
||||||
if (ptr_diff(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1), (char *)idlls[ic]->lookupt))
|
if (ptr_diff(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1), (char *)idlls[ic]->lookupt))
|
||||||
{
|
{
|
||||||
@ -1063,7 +1070,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
|||||||
}
|
}
|
||||||
ppi += 4;
|
ppi += 4;
|
||||||
assert(ppi < oimport+soimport);
|
assert(ppi < oimport+soimport);
|
||||||
soimport = ptr_diff(ppi,oimport);
|
soimport = ptr_diff_bytes(ppi,oimport);
|
||||||
|
|
||||||
if (soimport == 4)
|
if (soimport == 4)
|
||||||
soimport = 0;
|
soimport = 0;
|
||||||
@ -1088,7 +1095,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
|||||||
for (ic = 0; ic < dllnum; ic++, im++)
|
for (ic = 0; ic < dllnum; ic++, im++)
|
||||||
{
|
{
|
||||||
memset(im,FILLVAL,sizeof(*im));
|
memset(im,FILLVAL,sizeof(*im));
|
||||||
im->dllname = ptr_diff(dlls[idlls[ic]->original_position].name,ibuf);
|
im->dllname = ptr_diff_bytes(dlls[idlls[ic]->original_position].name,ibuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1250,14 +1257,14 @@ void PeFile::processExports(Export *xport) // pass1
|
|||||||
xport->convert(IDADDR(PEDIR_EXPORT),IDSIZE(PEDIR_EXPORT));
|
xport->convert(IDADDR(PEDIR_EXPORT),IDSIZE(PEDIR_EXPORT));
|
||||||
soexport = ALIGN_UP(xport->getsize(), 4u);
|
soexport = ALIGN_UP(xport->getsize(), 4u);
|
||||||
mb_oexport.alloc(soexport);
|
mb_oexport.alloc(soexport);
|
||||||
oexport = (upx_byte *)mb_oexport.getVoidPtr();
|
mb_oexport.clear();
|
||||||
memset(oexport, 0, soexport);
|
oexport = mb_oexport;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeFile::processExports(Export *xport,unsigned newoffs) // pass2
|
void PeFile::processExports(Export *xport,unsigned newoffs) // pass2
|
||||||
{
|
{
|
||||||
if (soexport)
|
if (soexport)
|
||||||
xport->build((char*) oexport,newoffs);
|
xport->build((char *) raw_bytes(oexport, 0), newoffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1382,8 +1389,8 @@ void PeFile::processTls1(Interval *iv,
|
|||||||
|
|
||||||
// the PE loader wants this stuff uncompressed
|
// the PE loader wants this stuff uncompressed
|
||||||
mb_otls.alloc(sotls);
|
mb_otls.alloc(sotls);
|
||||||
otls = (upx_byte *)mb_otls.getVoidPtr();
|
mb_otls.clear();
|
||||||
memset(otls,0,sotls);
|
otls = mb_otls; // => SPAN_S
|
||||||
unsigned const take1 = sizeof(tls);
|
unsigned const take1 = sizeof(tls);
|
||||||
unsigned const skip1 = IDADDR(PEDIR_TLS);
|
unsigned const skip1 = IDADDR(PEDIR_TLS);
|
||||||
memcpy(otls,ibuf.subref("bad tls %#x", skip1, take1), take1);
|
memcpy(otls,ibuf.subref("bad tls %#x", skip1, take1), take1);
|
||||||
@ -1422,16 +1429,17 @@ void PeFile::processTls2(Reloc *rel,const Interval *iv,unsigned newaddr,
|
|||||||
for (ic = 0; ic < (use_tls_callbacks ? 4 * cb_size : 3 * cb_size); ic += cb_size)
|
for (ic = 0; ic < (use_tls_callbacks ? 4 * cb_size : 3 * cb_size); ic += cb_size)
|
||||||
rel->add(newaddr + ic, reloc_type);
|
rel->add(newaddr + ic, reloc_type);
|
||||||
|
|
||||||
tls * const tlsp = (tls*) otls;
|
SPAN_S_VAR(tls, const tlsp, mb_otls);
|
||||||
// now the relocation entries in the tls data area
|
// now the relocation entries in the tls data area
|
||||||
for (ic = 0; ic < iv->ivnum; ic += 4)
|
for (ic = 0; ic < iv->ivnum; ic += 4)
|
||||||
{
|
{
|
||||||
void *p = otls + iv->ivarr[ic].start - (tlsp->datastart - imagebase) + sizeof(tls);
|
SPAN_S_VAR(upx_byte, pp, otls + (iv->ivarr[ic].start - (tlsp->datastart - imagebase) + sizeof(tls)));
|
||||||
cb_value_t kc = *(LEXX*)(p);
|
LEXX * const p = (LEXX *) raw_bytes(pp, sizeof(LEXX));
|
||||||
|
cb_value_t kc = *p;
|
||||||
if (kc < tlsp->dataend && kc >= tlsp->datastart)
|
if (kc < tlsp->dataend && kc >= tlsp->datastart)
|
||||||
{
|
{
|
||||||
kc += newaddr + sizeof(tls) - tlsp->datastart;
|
kc += newaddr + sizeof(tls) - tlsp->datastart;
|
||||||
*(LEXX*)(p) = kc + imagebase;
|
*p = kc + imagebase;
|
||||||
rel->add(kc,iv->ivarr[ic].len);
|
rel->add(kc,iv->ivarr[ic].len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1442,16 +1450,19 @@ void PeFile::processTls2(Reloc *rel,const Interval *iv,unsigned newaddr,
|
|||||||
tlsp->datastart = newaddr + sizeof(tls) + imagebase;
|
tlsp->datastart = newaddr + sizeof(tls) + imagebase;
|
||||||
tlsp->dataend = tlsp->datastart + tls_data_size;
|
tlsp->dataend = tlsp->datastart + tls_data_size;
|
||||||
|
|
||||||
//NEW: if we have TLS callbacks to handle, we create a pointer to the new callback chain - Stefan Widmann
|
// NEW: if we have TLS callbacks to handle, we create a pointer to the new callback chain - Stefan Widmann
|
||||||
tlsp->callbacks = (use_tls_callbacks ? newaddr + sotls + imagebase - 2 * cb_size : 0);
|
tlsp->callbacks = (use_tls_callbacks ? newaddr + sotls + imagebase - 2 * cb_size : 0);
|
||||||
|
|
||||||
if (use_tls_callbacks)
|
if (use_tls_callbacks)
|
||||||
{
|
{
|
||||||
//set handler offset
|
// set handler offset
|
||||||
*(LEXX*)(otls + sotls - 2 * cb_size) = tls_handler_offset + imagebase;
|
SPAN_S_VAR(upx_byte, pp, otls);
|
||||||
*(LEXX*)(otls + sotls - 1 * cb_size) = 0; // end of one-item list
|
pp = otls + (sotls - 2 * cb_size);
|
||||||
//add relocation for TLS handler offset
|
* (LEXX *) raw_bytes(pp, sizeof(LEXX)) = tls_handler_offset + imagebase;
|
||||||
rel->add(newaddr + sotls - 2 * cb_size, reloc_type);
|
pp = otls + (sotls - 1 * cb_size);
|
||||||
|
* (LEXX *) raw_bytes(pp, sizeof(LEXX)) = 0; // end of one-item list
|
||||||
|
// add relocation for TLS handler offset
|
||||||
|
rel->add(newaddr + sotls - 2 * cb_size, reloc_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1947,8 +1958,9 @@ void PeFile::processResources(Resource *res)
|
|||||||
for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size())
|
for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size())
|
||||||
;
|
;
|
||||||
mb_oresources.alloc(soresources);
|
mb_oresources.alloc(soresources);
|
||||||
oresources = (upx_byte *)mb_oresources.getVoidPtr();
|
mb_oresources.clear();
|
||||||
upx_byte *ores = oresources + res->dirsize();
|
oresources = mb_oresources; // => SPAN_S
|
||||||
|
SPAN_S_VAR(upx_byte, ores, oresources + res->dirsize());
|
||||||
|
|
||||||
char *keep_icons = nullptr; // icon ids in the first icon group
|
char *keep_icons = nullptr; // icon ids in the first icon group
|
||||||
unsigned iconsin1stdir = 0;
|
unsigned iconsin1stdir = 0;
|
||||||
@ -2026,14 +2038,14 @@ void PeFile::processResources(Resource *res)
|
|||||||
ICHECK(ibuf + res->offs(), take);
|
ICHECK(ibuf + res->offs(), take);
|
||||||
memcpy(ores, ibuf.subref("bad resoff %#x", res->offs(), take), take);
|
memcpy(ores, ibuf.subref("bad resoff %#x", res->offs(), take), take);
|
||||||
ibuf.fill(res->offs(), take, FILLVAL);
|
ibuf.fill(res->offs(), take, FILLVAL);
|
||||||
res->newoffs() = ptr_diff(ores,oresources);
|
res->newoffs() = ptr_diff_bytes(ores,oresources);
|
||||||
if (rtype == RT_ICON && opt->win32_pe.compress_icons == 1)
|
if (rtype == RT_ICON && opt->win32_pe.compress_icons == 1)
|
||||||
compress_icon = true;
|
compress_icon = true;
|
||||||
else if (rtype == RT_GROUP_ICON)
|
else if (rtype == RT_GROUP_ICON)
|
||||||
{
|
{
|
||||||
if (opt->win32_pe.compress_icons == 1)
|
if (opt->win32_pe.compress_icons == 1)
|
||||||
{
|
{
|
||||||
icondir_offset = 4 + ptr_diff(ores,oresources);
|
icondir_offset = 4 + ptr_diff_bytes(ores,oresources);
|
||||||
icondir_count = get_le16(oresources + icondir_offset);
|
icondir_count = get_le16(oresources + icondir_offset);
|
||||||
set_le16(oresources + icondir_offset,1);
|
set_le16(oresources + icondir_offset,1);
|
||||||
}
|
}
|
||||||
@ -2041,7 +2053,7 @@ void PeFile::processResources(Resource *res)
|
|||||||
}
|
}
|
||||||
ores += res->size();
|
ores += res->size();
|
||||||
}
|
}
|
||||||
soresources = ptr_diff(ores,oresources);
|
soresources = ptr_diff_bytes(ores,oresources);
|
||||||
|
|
||||||
delete[] keep_icons;
|
delete[] keep_icons;
|
||||||
if (!res->clear())
|
if (!res->clear())
|
||||||
@ -2446,7 +2458,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
|
|||||||
s += 2;
|
s += 2;
|
||||||
}
|
}
|
||||||
// end of extra data
|
// end of extra data
|
||||||
set_le32(p1 + s,ptr_diff(p1,ibuf) - rvamin);
|
set_le32(p1 + s,ptr_diff_bytes(p1,ibuf) - rvamin);
|
||||||
s += 4;
|
s += 4;
|
||||||
ph.u_len += s;
|
ph.u_len += s;
|
||||||
obuf.allocForCompression(ph.u_len);
|
obuf.allocForCompression(ph.u_len);
|
||||||
@ -2710,16 +2722,16 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
|
|||||||
OutputFile::dump(opt->debug.dump_stub_loader, loader, codesize);
|
OutputFile::dump(opt->debug.dump_stub_loader, loader, codesize);
|
||||||
if ((ic = fo->getBytesWritten() & (sizeof(LEXX) - 1)) != 0)
|
if ((ic = fo->getBytesWritten() & (sizeof(LEXX) - 1)) != 0)
|
||||||
fo->write(ibuf, sizeof(LEXX) - ic);
|
fo->write(ibuf, sizeof(LEXX) - ic);
|
||||||
fo->write(otls, aligned_sotls);
|
fo->write(raw_bytes(otls, aligned_sotls), aligned_sotls);
|
||||||
fo->write(oloadconf, soloadconf);
|
fo->write(oloadconf, soloadconf);
|
||||||
if ((ic = fo->getBytesWritten() & fam1) != 0)
|
if ((ic = fo->getBytesWritten() & fam1) != 0)
|
||||||
fo->write(ibuf,oh.filealign - ic);
|
fo->write(ibuf,oh.filealign - ic);
|
||||||
if (!last_section_rsrc_only)
|
if (!last_section_rsrc_only)
|
||||||
fo->write(oresources,soresources);
|
fo->write(raw_bytes(oresources, soresources) ,soresources);
|
||||||
else
|
else
|
||||||
fo->write(oxrelocs,soxrelocs);
|
fo->write(oxrelocs,soxrelocs);
|
||||||
fo->write(oimpdlls,soimpdlls);
|
fo->write(oimpdlls,soimpdlls);
|
||||||
fo->write(oexport,soexport);
|
fo->write(raw_bytes(oexport, soexport), soexport);
|
||||||
if (!last_section_rsrc_only)
|
if (!last_section_rsrc_only)
|
||||||
fo->write(oxrelocs,soxrelocs);
|
fo->write(oxrelocs,soxrelocs);
|
||||||
|
|
||||||
@ -2728,7 +2740,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
|
|||||||
|
|
||||||
if (last_section_rsrc_only)
|
if (last_section_rsrc_only)
|
||||||
{
|
{
|
||||||
fo->write(oresources,soresources);
|
fo->write(raw_bytes(oresources, soresources) ,soresources);
|
||||||
if ((ic = fo->getBytesWritten() & fam1) != 0)
|
if ((ic = fo->getBytesWritten() & fam1) != 0)
|
||||||
fo->write(ibuf,oh.filealign - ic);
|
fo->write(ibuf,oh.filealign - ic);
|
||||||
}
|
}
|
||||||
@ -2752,7 +2764,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
|
|||||||
verifyOverlappingDecompression();
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, obuf);
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
@ -2763,7 +2775,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
|
|||||||
// unpack
|
// unpack
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void PeFile::rebuildRelocs(upx_byte *& extrainfo, unsigned bits,
|
void PeFile::rebuildRelocs(SPAN_S(upx_byte) & extrainfo, unsigned bits,
|
||||||
unsigned flags, upx_uint64_t imagebase)
|
unsigned flags, upx_uint64_t imagebase)
|
||||||
{
|
{
|
||||||
assert(bits == 32 || bits == 64);
|
assert(bits == 32 || bits == 64);
|
||||||
@ -2776,18 +2788,17 @@ void PeFile::rebuildRelocs(upx_byte *& extrainfo, unsigned bits,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_byte *rdata = obuf + get_le32(extrainfo);
|
SPAN_P_VAR(upx_byte, rdata, obuf);
|
||||||
|
rdata += get_le32(extrainfo);
|
||||||
const upx_byte big = extrainfo[4];
|
const upx_byte big = extrainfo[4];
|
||||||
extrainfo += 5;
|
extrainfo += 5;
|
||||||
|
|
||||||
// upx_byte *p = rdata;
|
MemBuffer mb_wrkmem;
|
||||||
OPTR_I(upx_byte, p, rdata);
|
unsigned relocn = unoptimizeReloc(rdata,obuf,mb_wrkmem,true,bits);
|
||||||
MemBuffer wrkmem;
|
|
||||||
unsigned relocn = unoptimizeReloc(&rdata,obuf,&wrkmem,1,bits);
|
|
||||||
unsigned r16 = 0;
|
unsigned r16 = 0;
|
||||||
if (big & 6) // 16 bit relocations
|
if (big & 6) // 16 bit relocations
|
||||||
{
|
{
|
||||||
const LE32 *q = (LE32*) rdata;
|
SPAN_S_VAR(const LE32, q, (const LE32 *) raw_bytes(rdata, 0), obuf);
|
||||||
while (*q++)
|
while (*q++)
|
||||||
r16++;
|
r16++;
|
||||||
if ((big & 6) == 6)
|
if ((big & 6) == 6)
|
||||||
@ -2798,31 +2809,30 @@ void PeFile::rebuildRelocs(upx_byte *& extrainfo, unsigned bits,
|
|||||||
|
|
||||||
if (big & 6)
|
if (big & 6)
|
||||||
{
|
{
|
||||||
LE32 *q = (LE32*) rdata;
|
SPAN_S_VAR(LE32, q, (LE32 *) raw_bytes(rdata, 0), obuf);
|
||||||
while (*q)
|
while (*q)
|
||||||
rel.add(*q++ + rvamin,(big & 4) ? 2 : 1);
|
rel.add(*q++ + rvamin,(big & 4) ? 2 : 1);
|
||||||
if ((big & 6) == 6)
|
if ((big & 6) == 6)
|
||||||
while (*++q)
|
while (*++q)
|
||||||
rel.add(*q + rvamin,1);
|
rel.add(*q + rvamin,1);
|
||||||
rdata = (upx_byte*) q;
|
// rdata = (upx_byte *) raw_bytes(q, 0); // ???
|
||||||
}
|
}
|
||||||
|
|
||||||
//memset(p,0,rdata - p);
|
SPAN_S_VAR(upx_byte, const wrkmem, mb_wrkmem);
|
||||||
|
|
||||||
for (unsigned ic = 0; ic < relocn; ic++)
|
for (unsigned ic = 0; ic < relocn; ic++)
|
||||||
{
|
{
|
||||||
p = obuf + get_le32(wrkmem + 4 * ic);
|
OPTR_I(upx_byte, p, obuf + get_le32(wrkmem + 4 * ic));
|
||||||
if (bits == 32)
|
if (bits == 32)
|
||||||
set_le32(p, get_le32((unsigned char *)p) + imagebase + rvamin);
|
set_le32(p, get_le32(p) + imagebase + rvamin);
|
||||||
else
|
else
|
||||||
set_le64(p, get_le64((unsigned char *)p) + imagebase + rvamin);
|
set_le64(p, get_le64(p) + imagebase + rvamin);
|
||||||
rel.add(rvamin + get_le32(wrkmem + 4 * ic), bits == 32 ? 3 : 10);
|
rel.add(rvamin + get_le32(wrkmem + 4 * ic), bits == 32 ? 3 : 10);
|
||||||
}
|
}
|
||||||
rel.finish (oxrelocs,soxrelocs);
|
rel.finish (oxrelocs,soxrelocs);
|
||||||
|
|
||||||
omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);
|
omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);
|
||||||
delete [] oxrelocs; oxrelocs = nullptr;
|
delete [] oxrelocs; oxrelocs = nullptr;
|
||||||
wrkmem.dealloc();
|
mb_wrkmem.dealloc();
|
||||||
|
|
||||||
ODSIZE(PEDIR_RELOC) = soxrelocs;
|
ODSIZE(PEDIR_RELOC) = soxrelocs;
|
||||||
}
|
}
|
||||||
@ -2836,7 +2846,7 @@ void PeFile::rebuildExports()
|
|||||||
Export xport((char*)(unsigned char*) ibuf - isection[2].vaddr);
|
Export xport((char*)(unsigned char*) ibuf - isection[2].vaddr);
|
||||||
processExports(&xport);
|
processExports(&xport);
|
||||||
processExports(&xport,ODADDR(PEDIR_EXPORT));
|
processExports(&xport,ODADDR(PEDIR_EXPORT));
|
||||||
omemcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin,oexport,soexport);
|
omemcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin, oexport, soexport);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeFile::rebuildTls()
|
void PeFile::rebuildTls()
|
||||||
@ -2844,7 +2854,7 @@ void PeFile::rebuildTls()
|
|||||||
// this is an easy one : just do nothing ;-)
|
// this is an easy one : just do nothing ;-)
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeFile::rebuildResources(upx_byte *& extrainfo, unsigned lastvaddr)
|
void PeFile::rebuildResources(SPAN_S(upx_byte) & extrainfo, unsigned lastvaddr)
|
||||||
{
|
{
|
||||||
if (ODSIZE(PEDIR_RESOURCE) == 0 || IDSIZE(PEDIR_RESOURCE) == 0)
|
if (ODSIZE(PEDIR_RESOURCE) == 0 || IDSIZE(PEDIR_RESOURCE) == 0)
|
||||||
return;
|
return;
|
||||||
@ -2857,7 +2867,8 @@ void PeFile::rebuildResources(upx_byte *& extrainfo, unsigned lastvaddr)
|
|||||||
if (lastvaddr > vaddr || (vaddr - lastvaddr) > ibuf.getSize())
|
if (lastvaddr > vaddr || (vaddr - lastvaddr) > ibuf.getSize())
|
||||||
throwCantUnpack("corrupted PE header");
|
throwCantUnpack("corrupted PE header");
|
||||||
|
|
||||||
const upx_byte *r = ibuf - lastvaddr;
|
// TODO: introduce WildPtr for "virtual pointer" pointing before a buffer
|
||||||
|
const upx_byte *r = ibuf.raw_bytes(0) - lastvaddr;
|
||||||
Resource res(r + vaddr, ibuf, ibuf + ibuf.getSize());
|
Resource res(r + vaddr, ibuf, ibuf + ibuf.getSize());
|
||||||
while (res.next())
|
while (res.next())
|
||||||
if (res.offs() > vaddr)
|
if (res.offs() > vaddr)
|
||||||
@ -2882,29 +2893,25 @@ void PeFile::rebuildResources(upx_byte *& extrainfo, unsigned lastvaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename LEXX, typename ord_mask_t>
|
template <typename LEXX, typename ord_mask_t>
|
||||||
void PeFile::rebuildImports(upx_byte *& extrainfo,
|
void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo,
|
||||||
ord_mask_t ord_mask, bool set_oft)
|
ord_mask_t ord_mask, bool set_oft)
|
||||||
{
|
{
|
||||||
if (ODADDR(PEDIR_IMPORT) == 0
|
if (ODADDR(PEDIR_IMPORT) == 0
|
||||||
|| ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc))
|
|| ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// const upx_byte * const idata = obuf + get_le32(extrainfo);
|
|
||||||
OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo));
|
OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo));
|
||||||
const unsigned inamespos = get_le32(extrainfo + 4);
|
const unsigned inamespos = get_le32(extrainfo + 4);
|
||||||
extrainfo += 8;
|
extrainfo += 8;
|
||||||
|
|
||||||
unsigned sdllnames = 0;
|
unsigned sdllnames = 0;
|
||||||
|
|
||||||
// const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr;
|
|
||||||
// const upx_byte *p;
|
|
||||||
IPTR_I_D(const upx_byte, import, IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
|
IPTR_I_D(const upx_byte, import, IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
|
||||||
OPTR(const upx_byte, p);
|
OPTR_I(const upx_byte, p, raw_bytes(idata, 4));
|
||||||
|
|
||||||
for (p = idata; get_le32(p) != 0; ++p)
|
for ( ; get_le32(p) != 0; ++p)
|
||||||
{
|
{
|
||||||
const upx_byte *dname = get_le32(p) + import;
|
const upx_byte *dname = raw_bytes(import + get_le32(p), 1);
|
||||||
ICHECK(dname, 1);
|
|
||||||
const unsigned dlen = strlen(dname);
|
const unsigned dlen = strlen(dname);
|
||||||
ICHECK(dname, dlen + 1);
|
ICHECK(dname, dlen + 1);
|
||||||
|
|
||||||
@ -2919,18 +2926,26 @@ void PeFile::rebuildImports(upx_byte *& extrainfo,
|
|||||||
}
|
}
|
||||||
sdllnames = ALIGN_UP(sdllnames, 2u);
|
sdllnames = ALIGN_UP(sdllnames, 2u);
|
||||||
|
|
||||||
upx_byte * const Obuf = obuf - rvamin;
|
// TODO: introduce WildPtr for "virtual pointer" pointing before a buffer
|
||||||
|
upx_byte * const Obuf = obuf.raw_bytes(0) - rvamin;
|
||||||
|
#if 0
|
||||||
import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT));
|
import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT));
|
||||||
import_desc *im = im0;
|
import_desc *im = im0;
|
||||||
upx_byte *dllnames = Obuf + inamespos;
|
upx_byte *dllnames = Obuf + inamespos;
|
||||||
upx_byte *importednames = dllnames + sdllnames;
|
upx_byte *importednames = dllnames + sdllnames;
|
||||||
upx_byte * const importednames_start = importednames;
|
upx_byte * const importednames_start = importednames;
|
||||||
|
#else
|
||||||
|
SPAN_S_VAR(import_desc, const im0, (import_desc *) (Obuf + ODADDR(PEDIR_IMPORT)), obuf);
|
||||||
|
SPAN_S_VAR(import_desc, im, im0);
|
||||||
|
SPAN_0_VAR(upx_byte, dllnames, inamespos ? Obuf + inamespos : nullptr, obuf);
|
||||||
|
SPAN_0_VAR(upx_byte, importednames, inamespos ? dllnames + sdllnames : nullptr);
|
||||||
|
SPAN_0_VAR(upx_byte, const importednames_start, importednames);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (p = idata; get_le32(p) != 0; ++p)
|
for (p = idata; get_le32(p) != 0; ++p)
|
||||||
{
|
{
|
||||||
// restore the name of the dll
|
// restore the name of the dll
|
||||||
const upx_byte *dname = get_le32(p) + import;
|
const upx_byte *dname = raw_bytes(import + get_le32(p), 1);
|
||||||
ICHECK(dname, 1);
|
|
||||||
const unsigned dlen = strlen(dname);
|
const unsigned dlen = strlen(dname);
|
||||||
ICHECK(dname, dlen + 1);
|
ICHECK(dname, dlen + 1);
|
||||||
|
|
||||||
@ -2939,7 +2954,7 @@ void PeFile::rebuildImports(upx_byte *& extrainfo,
|
|||||||
{
|
{
|
||||||
// now I rebuild the dll names
|
// now I rebuild the dll names
|
||||||
omemcpy(dllnames, dname, dlen + 1);
|
omemcpy(dllnames, dname, dlen + 1);
|
||||||
im->dllname = ptr_diff(dllnames,Obuf);
|
im->dllname = ptr_diff_bytes(dllnames,Obuf);
|
||||||
//;;;printf("\ndll: %s:",dllnames);
|
//;;;printf("\ndll: %s:",dllnames);
|
||||||
dllnames += dlen + 1;
|
dllnames += dlen + 1;
|
||||||
}
|
}
|
||||||
@ -2960,11 +2975,11 @@ void PeFile::rebuildImports(upx_byte *& extrainfo,
|
|||||||
const unsigned ilen = strlen(++p) + 1;
|
const unsigned ilen = strlen(++p) + 1;
|
||||||
if (inamespos)
|
if (inamespos)
|
||||||
{
|
{
|
||||||
if (ptr_diff(importednames, importednames_start) & 1)
|
if (ptr_diff_bytes(importednames, importednames_start) & 1)
|
||||||
importednames -= 1;
|
importednames -= 1;
|
||||||
omemcpy(importednames + 2, p, ilen);
|
omemcpy(importednames + 2, p, ilen);
|
||||||
//;;;printf(" %s",importednames+2);
|
//;;;printf(" %s",importednames+2);
|
||||||
*newiat = ptr_diff(importednames, Obuf);
|
*newiat = ptr_diff_bytes(importednames, Obuf);
|
||||||
importednames += 2 + ilen;
|
importednames += 2 + ilen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2982,7 +2997,7 @@ void PeFile::rebuildImports(upx_byte *& extrainfo,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*newiat = *(const LEXX*)(get_le32(p + 1) + import);
|
*newiat = * (const LEXX*) raw_bytes(import + get_le32(p + 1), sizeof(LEXX));
|
||||||
assert(*newiat & ord_mask);
|
assert(*newiat & ord_mask);
|
||||||
p += 5;
|
p += 5;
|
||||||
}
|
}
|
||||||
@ -3017,8 +3032,9 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh,
|
|||||||
decompress(ibuf,obuf);
|
decompress(ibuf,obuf);
|
||||||
unsigned skip = get_le32(obuf + ph.u_len - 4);
|
unsigned skip = get_le32(obuf + ph.u_len - 4);
|
||||||
unsigned take = sizeof(oh);
|
unsigned take = sizeof(oh);
|
||||||
upx_byte *extrainfo = obuf.subref("bad extrainfo offset %#x", skip, take);
|
SPAN_S_VAR(upx_byte, extrainfo, obuf);
|
||||||
//upx_byte * const eistart = extrainfo;
|
extrainfo = obuf.subref("bad extrainfo offset %#x", skip, take);
|
||||||
|
//upx_byte * const eistart = raw_bytes(extrainfo, 0);
|
||||||
|
|
||||||
memcpy(&oh, extrainfo, take);
|
memcpy(&oh, extrainfo, take);
|
||||||
extrainfo += take;
|
extrainfo += take;
|
||||||
@ -3080,7 +3096,7 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh,
|
|||||||
|
|
||||||
//FIXME: this does bad things if the relocation section got removed
|
//FIXME: this does bad things if the relocation section got removed
|
||||||
// during compression ...
|
// during compression ...
|
||||||
//memset(eistart,0,extrainfo - eistart + 4);
|
//memset(eistart, 0, ptr_udiff_bytes(extrainfo, eistart) + 4);
|
||||||
|
|
||||||
// fill the data directory
|
// fill the data directory
|
||||||
ODADDR(PEDIR_DEBUG) = 0;
|
ODADDR(PEDIR_DEBUG) = 0;
|
||||||
@ -3112,7 +3128,7 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh,
|
|||||||
for (ic = 0; ic < objs; ic++)
|
for (ic = 0; ic < objs; ic++)
|
||||||
if (osection[ic].rawdataptr)
|
if (osection[ic].rawdataptr)
|
||||||
fo->write(obuf + osection[ic].vaddr - rvamin,ALIGN_UP(osection[ic].size,oh.filealign));
|
fo->write(obuf + osection[ic].vaddr - rvamin,ALIGN_UP(osection[ic].size,oh.filealign));
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, obuf);
|
||||||
}
|
}
|
||||||
ibuf.dealloc();
|
ibuf.dealloc();
|
||||||
}
|
}
|
||||||
|
|||||||
56
src/pefile.h
56
src/pefile.h
@ -29,7 +29,7 @@
|
|||||||
#ifndef __UPX_PEFILE_H
|
#ifndef __UPX_PEFILE_H
|
||||||
#define __UPX_PEFILE_H 1
|
#define __UPX_PEFILE_H 1
|
||||||
|
|
||||||
#include "mem.h"
|
#include "util/membuffer.h"
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -40,7 +40,7 @@ class PeFile : public Packer
|
|||||||
{
|
{
|
||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
virtual int getVersion() const { return 13; }
|
virtual int getVersion() const override { return 13; }
|
||||||
protected:
|
protected:
|
||||||
class Interval;
|
class Interval;
|
||||||
class Reloc;
|
class Reloc;
|
||||||
@ -84,7 +84,7 @@ protected:
|
|||||||
ord_mask_t ord_mask, bool set_oft);
|
ord_mask_t ord_mask, bool set_oft);
|
||||||
|
|
||||||
// unpacker capabilities
|
// unpacker capabilities
|
||||||
virtual bool canUnpackVersion(int version) const
|
virtual bool canUnpackVersion(int version) const override
|
||||||
{ return (version >= 12 && version <= 13); }
|
{ return (version >= 12 && version <= 13); }
|
||||||
|
|
||||||
int canUnpack0(unsigned max_sections, LE16 &ih_objects,
|
int canUnpack0(unsigned max_sections, LE16 &ih_objects,
|
||||||
@ -92,7 +92,7 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int readFileHeader();
|
virtual int readFileHeader();
|
||||||
virtual bool testUnpackVersion(int version) const;
|
virtual bool testUnpackVersion(int version) const override;
|
||||||
virtual void readPeHeader() = 0;
|
virtual void readPeHeader() = 0;
|
||||||
|
|
||||||
unsigned pe_offset;
|
unsigned pe_offset;
|
||||||
@ -101,12 +101,12 @@ protected:
|
|||||||
unsigned processImports0(ord_mask_t ord_mask);
|
unsigned processImports0(ord_mask_t ord_mask);
|
||||||
|
|
||||||
template <typename LEXX, typename ord_mask_t>
|
template <typename LEXX, typename ord_mask_t>
|
||||||
void rebuildImports(upx_byte *& extrainfo,
|
void rebuildImports(SPAN_S(upx_byte) & extrainfo,
|
||||||
ord_mask_t ord_mask, bool set_oft);
|
ord_mask_t ord_mask, bool set_oft);
|
||||||
virtual unsigned processImports() = 0;
|
virtual unsigned processImports() = 0;
|
||||||
virtual void processImports2(unsigned, unsigned);
|
virtual void processImports2(unsigned, unsigned);
|
||||||
MemBuffer mb_oimport;
|
MemBuffer mb_oimport;
|
||||||
upx_byte *oimport;
|
SPAN_0(upx_byte) oimport = nullptr;
|
||||||
unsigned soimport;
|
unsigned soimport;
|
||||||
upx_byte *oimpdlls;
|
upx_byte *oimpdlls;
|
||||||
unsigned soimpdlls;
|
unsigned soimpdlls;
|
||||||
@ -118,26 +118,26 @@ protected:
|
|||||||
|
|
||||||
virtual void processRelocs() = 0;
|
virtual void processRelocs() = 0;
|
||||||
void processRelocs(Reloc *);
|
void processRelocs(Reloc *);
|
||||||
void rebuildRelocs(upx_byte *&, unsigned bits,
|
void rebuildRelocs(SPAN_S(upx_byte) &, unsigned bits,
|
||||||
unsigned flags, upx_uint64_t imagebase);
|
unsigned flags, upx_uint64_t imagebase);
|
||||||
MemBuffer mb_orelocs;
|
MemBuffer mb_orelocs;
|
||||||
upx_byte *orelocs;
|
SPAN_0(upx_byte) orelocs = nullptr;
|
||||||
unsigned sorelocs;
|
unsigned sorelocs;
|
||||||
upx_byte *oxrelocs;
|
upx_byte *oxrelocs = nullptr;
|
||||||
unsigned soxrelocs;
|
unsigned soxrelocs;
|
||||||
|
|
||||||
void processExports(Export *);
|
void processExports(Export *);
|
||||||
void processExports(Export *,unsigned);
|
void processExports(Export *,unsigned);
|
||||||
void rebuildExports();
|
void rebuildExports();
|
||||||
MemBuffer mb_oexport;
|
MemBuffer mb_oexport;
|
||||||
upx_byte *oexport;
|
SPAN_0(upx_byte) oexport = nullptr;
|
||||||
unsigned soexport;
|
unsigned soexport;
|
||||||
|
|
||||||
void processResources(Resource *);
|
void processResources(Resource *);
|
||||||
void processResources(Resource *, unsigned);
|
void processResources(Resource *, unsigned);
|
||||||
void rebuildResources(upx_byte *&, unsigned);
|
void rebuildResources(SPAN_S(upx_byte) &, unsigned);
|
||||||
MemBuffer mb_oresources;
|
MemBuffer mb_oresources;
|
||||||
upx_byte *oresources;
|
SPAN_0(upx_byte) oresources = nullptr;
|
||||||
unsigned soresources;
|
unsigned soresources;
|
||||||
|
|
||||||
template <typename>
|
template <typename>
|
||||||
@ -154,7 +154,7 @@ protected:
|
|||||||
|
|
||||||
void rebuildTls();
|
void rebuildTls();
|
||||||
MemBuffer mb_otls;
|
MemBuffer mb_otls;
|
||||||
upx_byte *otls;
|
SPAN_0(upx_byte) otls = nullptr;
|
||||||
unsigned sotls;
|
unsigned sotls;
|
||||||
unsigned tlsindex;
|
unsigned tlsindex;
|
||||||
unsigned tlscb_ptr;
|
unsigned tlscb_ptr;
|
||||||
@ -357,7 +357,7 @@ protected:
|
|||||||
const unsigned *getcounts() const { return counts; }
|
const unsigned *getcounts() const { return counts; }
|
||||||
//
|
//
|
||||||
void add(unsigned pos,unsigned type);
|
void add(unsigned pos,unsigned type);
|
||||||
void finish(upx_byte *&p,unsigned &size);
|
void finish(upx_byte* &p,unsigned &size);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Resource : private noncopyable
|
class Resource : private noncopyable
|
||||||
@ -460,15 +460,15 @@ protected:
|
|||||||
virtual ~PeFile32();
|
virtual ~PeFile32();
|
||||||
void pack0(OutputFile *fo, unsigned subsystem_mask,
|
void pack0(OutputFile *fo, unsigned subsystem_mask,
|
||||||
upx_uint64_t default_imagebase, bool last_section_rsrc_only);
|
upx_uint64_t default_imagebase, bool last_section_rsrc_only);
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo) override;
|
||||||
virtual int canUnpack();
|
virtual int canUnpack() override;
|
||||||
|
|
||||||
virtual void readPeHeader();
|
virtual void readPeHeader() override;
|
||||||
|
|
||||||
virtual unsigned processImports();
|
virtual unsigned processImports() override;
|
||||||
virtual void processRelocs();
|
virtual void processRelocs() override;
|
||||||
virtual void processTls(Interval *);
|
virtual void processTls(Interval *) override;
|
||||||
virtual void processTls(Reloc *, const Interval *, unsigned);
|
virtual void processTls(Reloc *, const Interval *, unsigned) override;
|
||||||
|
|
||||||
__packed_struct(pe_header_t)
|
__packed_struct(pe_header_t)
|
||||||
// 0x0
|
// 0x0
|
||||||
@ -522,15 +522,15 @@ protected:
|
|||||||
void pack0(OutputFile *fo, unsigned subsystem_mask,
|
void pack0(OutputFile *fo, unsigned subsystem_mask,
|
||||||
upx_uint64_t default_imagebase);
|
upx_uint64_t default_imagebase);
|
||||||
|
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo) override;
|
||||||
virtual int canUnpack();
|
virtual int canUnpack() override;
|
||||||
|
|
||||||
virtual void readPeHeader();
|
virtual void readPeHeader() override;
|
||||||
|
|
||||||
virtual unsigned processImports();
|
virtual unsigned processImports() override;
|
||||||
virtual void processRelocs();
|
virtual void processRelocs() override;
|
||||||
virtual void processTls(Interval *);
|
virtual void processTls(Interval *) override;
|
||||||
virtual void processTls(Reloc *, const Interval *, unsigned);
|
virtual void processTls(Reloc *, const Interval *, unsigned) override;
|
||||||
|
|
||||||
__packed_struct(pe_header_t)
|
__packed_struct(pe_header_t)
|
||||||
// 0x0
|
// 0x0
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0+
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// Copyright 2022 BitWagon Software LLC. All rights reserved.
|
// Copyright 2022 BitWagon Software LLC. All rights reserved.
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
1
src/ui.h
1
src/ui.h
@ -25,6 +25,7 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __UPX_UI_H
|
#ifndef __UPX_UI_H
|
||||||
#define __UPX_UI_H 1
|
#define __UPX_UI_H 1
|
||||||
|
|
||||||
|
|||||||
142
src/util/bptr.h
Normal file
142
src/util/bptr.h
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/* bptr.h --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2022 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef UPX_BPTR_H__
|
||||||
|
#define UPX_BPTR_H__ 1
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// BoundedPtr
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class BoundedPtr {
|
||||||
|
public:
|
||||||
|
~BoundedPtr() {}
|
||||||
|
|
||||||
|
BoundedPtr(void *base, size_t size_in_bytes, T *ptr = nullptr)
|
||||||
|
: ptr_(ptr), base_(base), size_in_bytes_(0) {
|
||||||
|
assert(base_ != nullptr);
|
||||||
|
size_in_bytes_ = mem_size(1, size_in_bytes);
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// assignment
|
||||||
|
BoundedPtr &operator=(const BoundedPtr &other) {
|
||||||
|
assert(base_ == other.base_);
|
||||||
|
assert(size_in_bytes_ == other.size_in_bytes_);
|
||||||
|
ptr_ = other.ptr_;
|
||||||
|
check();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
BoundedPtr &operator=(T *other) {
|
||||||
|
ptr_ = other;
|
||||||
|
check();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dereference
|
||||||
|
T &operator*() {
|
||||||
|
checkNULL();
|
||||||
|
checkRange(ptr_ + 1);
|
||||||
|
return *ptr_;
|
||||||
|
}
|
||||||
|
const T &operator*() const {
|
||||||
|
checkNULL();
|
||||||
|
checkRange(ptr_ + 1);
|
||||||
|
return *ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T *() { return ptr_; }
|
||||||
|
operator const T *() const { return ptr_; }
|
||||||
|
|
||||||
|
BoundedPtr &operator+=(size_t n) {
|
||||||
|
checkNULL();
|
||||||
|
ptr_ += n;
|
||||||
|
checkRange();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
BoundedPtr &operator-=(size_t n) {
|
||||||
|
checkNULL();
|
||||||
|
ptr_ -= n;
|
||||||
|
checkRange();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
BoundedPtr &operator++(void) {
|
||||||
|
checkNULL();
|
||||||
|
ptr_ += 1;
|
||||||
|
checkRange();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *raw_bytes(size_t bytes) const {
|
||||||
|
checkNULL();
|
||||||
|
if (bytes > 0)
|
||||||
|
checkRange((const char *) (const void *) ptr_ + bytes);
|
||||||
|
return ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkNULL() const {
|
||||||
|
if __acc_very_unlikely (!ptr_)
|
||||||
|
throwCantUnpack("unexpected NULL pointer; take care!");
|
||||||
|
}
|
||||||
|
__acc_forceinline void checkRange() const { checkRange(ptr_, base_, size_in_bytes_); }
|
||||||
|
__acc_forceinline void checkRange(const void *p) const { checkRange(p, base_, size_in_bytes_); }
|
||||||
|
static void checkRange(const void *ptr, const void *base, size_t size_in_bytes) {
|
||||||
|
size_t off = (const char *) ptr - (const char *) base;
|
||||||
|
if __acc_very_unlikely (off > size_in_bytes)
|
||||||
|
throwCantUnpack("pointer out of range; take care!");
|
||||||
|
}
|
||||||
|
void check() const { // check ptr_ invariant: either NULL or valid checkRange()
|
||||||
|
if (ptr_ != nullptr)
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
T *ptr_;
|
||||||
|
void *base_;
|
||||||
|
size_t size_in_bytes_;
|
||||||
|
|
||||||
|
// disable copy
|
||||||
|
BoundedPtr(const BoundedPtr &) = delete;
|
||||||
|
// disable dynamic allocation
|
||||||
|
ACC_CXX_DISABLE_NEW_DELETE
|
||||||
|
|
||||||
|
// disable taking the address => force passing by reference
|
||||||
|
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
||||||
|
BoundedPtr<T> *operator&() const = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
// raw_bytes overload
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const BoundedPtr<T> &a, size_t size_in_bytes) {
|
||||||
|
return a.raw_bytes(size_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
@ -25,36 +25,52 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "conf.h"
|
#include "../conf.h"
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// upx_doctest_check()
|
// upx_doctest_check()
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool upx_doctest_check(void) {
|
bool upx_doctest_check(int argc, char **argv) {
|
||||||
bool minimal = true; // only show failing tests
|
bool minimal = true; // only show failing tests
|
||||||
bool duration = false; // show timings
|
bool duration = false; // show timings
|
||||||
|
bool success = false; // show all tests
|
||||||
const char *e = getenv("UPX_DEBUG_DOCTEST_VERBOSE");
|
const char *e = getenv("UPX_DEBUG_DOCTEST_VERBOSE");
|
||||||
if (e && e[0] && strcmp(e, "0") != 0) {
|
if (e && e[0] && strcmp(e, "0") != 0) {
|
||||||
minimal = false;
|
minimal = false;
|
||||||
if (strcmp(e, "2") == 0)
|
if (strcmp(e, "2") == 0)
|
||||||
duration = true;
|
duration = true;
|
||||||
|
if (strcmp(e, "3") == 0) {
|
||||||
|
duration = true;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
minimal = false;
|
minimal = false;
|
||||||
// duration = true;
|
// duration = true;
|
||||||
#endif
|
#endif
|
||||||
doctest::Context context;
|
doctest::Context context;
|
||||||
|
#if 0
|
||||||
|
if (argc > 0 && argv != nullptr)
|
||||||
|
context.applyCommandLine(argc, argv);
|
||||||
|
#else
|
||||||
|
UNUSED(argc);
|
||||||
|
UNUSED(argv);
|
||||||
|
#endif
|
||||||
if (minimal)
|
if (minimal)
|
||||||
context.setOption("dt-minimal", true);
|
context.setOption("dt-minimal", true);
|
||||||
if (duration)
|
if (duration)
|
||||||
context.setOption("dt-duration", true);
|
context.setOption("dt-duration", true);
|
||||||
|
if (success)
|
||||||
|
context.setOption("dt-success", true);
|
||||||
int r = context.run();
|
int r = context.run();
|
||||||
if (context.shouldExit() || r != 0)
|
if (context.shouldExit() || r != 0)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool upx_doctest_check() { return upx_doctest_check(0, nullptr); }
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// compile-time checks
|
// compile-time checks
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@ -194,13 +210,13 @@ struct TestIntegerWrap {
|
|||||||
|
|
||||||
#define ACC_WANT_ACC_CHK_CH 1
|
#define ACC_WANT_ACC_CHK_CH 1
|
||||||
#undef ACCCHK_ASSERT
|
#undef ACCCHK_ASSERT
|
||||||
#include "miniacc.h"
|
#include "../miniacc.h"
|
||||||
|
|
||||||
void upx_compiler_sanity_check(void) {
|
void upx_compiler_sanity_check(void) {
|
||||||
#define ACC_WANT_ACC_CHK_CH 1
|
#define ACC_WANT_ACC_CHK_CH 1
|
||||||
#undef ACCCHK_ASSERT
|
#undef ACCCHK_ASSERT
|
||||||
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
|
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
|
||||||
#include "miniacc.h"
|
#include "../miniacc.h"
|
||||||
#undef ACCCHK_ASSERT
|
#undef ACCCHK_ASSERT
|
||||||
|
|
||||||
COMPILE_TIME_ASSERT(sizeof(char) == 1)
|
COMPILE_TIME_ASSERT(sizeof(char) == 1)
|
||||||
@ -390,11 +406,21 @@ TEST_CASE("working -fno-strict-overflow") {
|
|||||||
|
|
||||||
TEST_CASE("libc snprintf") {
|
TEST_CASE("libc snprintf") {
|
||||||
// runtime check that Win32/MinGW <stdio.h> works as expected
|
// runtime check that Win32/MinGW <stdio.h> works as expected
|
||||||
|
char buf[64];
|
||||||
long long ll = acc_vget_int(-1, 0);
|
long long ll = acc_vget_int(-1, 0);
|
||||||
unsigned long long llu = (unsigned long long) ll;
|
unsigned long long llu = (unsigned long long) ll;
|
||||||
char buf[64];
|
snprintf(buf, sizeof(buf), "%d.%ld.%lld.%u.%lu.%llu", -3, -2L, ll, 3U, 2LU, llu);
|
||||||
snprintf(buf, sizeof(buf), ".%d.%ld.%lld.%u.%lu.%llu", -3, -2L, ll, 3U, 2LU, llu);
|
CHECK_EQ(strcmp(buf, "-3.-2.-1.3.2.18446744073709551615"), 0);
|
||||||
CHECK_EQ(strcmp(buf, ".-3.-2.-1.3.2.18446744073709551615"), 0);
|
intmax_t im = ll;
|
||||||
|
uintmax_t um = llu;
|
||||||
|
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%jd", -4, 0, 0, 0, 0, 0, 0, 0, 4, im);
|
||||||
|
CHECK_EQ(strcmp(buf, "-4.0.0.0.0.0.0.0.4.-1"), 0);
|
||||||
|
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%ju", -5, 0, 0, 0, 0, 0, 0, 0, 5, um);
|
||||||
|
CHECK_EQ(strcmp(buf, "-5.0.0.0.0.0.0.0.5.18446744073709551615"), 0);
|
||||||
|
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%jx", -6, 0, 0, 0, 0, 0, 0, 0, 6, um);
|
||||||
|
CHECK_EQ(strcmp(buf, "-6.0.0.0.0.0.0.0.6.ffffffffffffffff"), 0);
|
||||||
|
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%#jx", -7, 0, 0, 0, 0, 0, 0, 0, 7, um);
|
||||||
|
CHECK_EQ(strcmp(buf, "-7.0.0.0.0.0.0.0.7.0xffffffffffffffff"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
@ -1,4 +1,4 @@
|
|||||||
/* mem.cpp --
|
/* membuffer.cpp --
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
@ -25,10 +25,12 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../conf.h"
|
||||||
|
#include "membuffer.h"
|
||||||
|
|
||||||
#include "conf.h"
|
// extra functions to reduce dependency on membuffer.h
|
||||||
#include "mem.h"
|
void *membuffer_get_void_ptr(MemBuffer &mb) { return mb.getVoidPtr(); }
|
||||||
|
unsigned membuffer_get_size(MemBuffer &mb) { return mb.getSize(); }
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// bool use_simple_mcheck()
|
// bool use_simple_mcheck()
|
||||||
@ -38,17 +40,15 @@
|
|||||||
__acc_static_forceinline constexpr bool use_simple_mcheck() { return false; }
|
__acc_static_forceinline constexpr bool use_simple_mcheck() { return false; }
|
||||||
#elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND)
|
#elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND)
|
||||||
static int use_simple_mcheck_flag = -1;
|
static int use_simple_mcheck_flag = -1;
|
||||||
__acc_static_noinline void use_simple_mcheck_init()
|
__acc_static_noinline void use_simple_mcheck_init() {
|
||||||
{
|
|
||||||
use_simple_mcheck_flag = 1;
|
use_simple_mcheck_flag = 1;
|
||||||
if (RUNNING_ON_VALGRIND) {
|
if (RUNNING_ON_VALGRIND) {
|
||||||
use_simple_mcheck_flag = 0;
|
use_simple_mcheck_flag = 0;
|
||||||
//fprintf(stderr, "upx: detected RUNNING_ON_VALGRIND\n");
|
// fprintf(stderr, "upx: detected RUNNING_ON_VALGRIND\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__acc_static_forceinline bool use_simple_mcheck()
|
__acc_static_forceinline bool use_simple_mcheck() {
|
||||||
{
|
if __acc_unlikely (use_simple_mcheck_flag < 0)
|
||||||
if __acc_unlikely(use_simple_mcheck_flag < 0)
|
|
||||||
use_simple_mcheck_init();
|
use_simple_mcheck_init();
|
||||||
return (bool) use_simple_mcheck_flag;
|
return (bool) use_simple_mcheck_flag;
|
||||||
}
|
}
|
||||||
@ -56,182 +56,166 @@ __acc_static_forceinline bool use_simple_mcheck()
|
|||||||
__acc_static_forceinline constexpr bool use_simple_mcheck() { return true; }
|
__acc_static_forceinline constexpr bool use_simple_mcheck() { return true; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
MemBuffer::MemBuffer(upx_uint64_t size) :
|
MemBuffer::MemBuffer(upx_uint64_t size_in_bytes) { alloc(size_in_bytes); }
|
||||||
b(nullptr), b_size(0)
|
|
||||||
{
|
|
||||||
alloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
MemBuffer::~MemBuffer() { this->dealloc(); }
|
||||||
MemBuffer::~MemBuffer()
|
|
||||||
{
|
|
||||||
this->dealloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
// similar to BoundedPtr, except checks only at creation
|
// similar to BoundedPtr, except checks only at creation
|
||||||
unsigned char *MemBuffer::subref(char const *errfmt, unsigned skip, unsigned take)
|
// skip == offset, take == size_in_bytes
|
||||||
{
|
void *MemBuffer::subref_impl(const char *errfmt, size_t skip, size_t take) {
|
||||||
if ((take + skip) < take // wrap-around
|
// check overrun and wrap-around
|
||||||
|| (take + skip) > b_size // overrun
|
if (skip + take > b_size_in_bytes || skip + take < skip) {
|
||||||
) {
|
char buf[100];
|
||||||
char buf[100]; snprintf(buf, sizeof(buf), errfmt, skip, take);
|
// printf is using unsigned formatting
|
||||||
|
if (!errfmt || !errfmt[0])
|
||||||
|
errfmt = "bad subref %#x %#x";
|
||||||
|
snprintf(buf, sizeof(buf), errfmt, (unsigned) skip, (unsigned) take);
|
||||||
throwCantPack(buf);
|
throwCantPack(buf);
|
||||||
}
|
}
|
||||||
return &b[skip];
|
return &b[skip];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemBuffer::dealloc()
|
static unsigned width(unsigned x) {
|
||||||
{
|
|
||||||
if (b != nullptr)
|
|
||||||
{
|
|
||||||
checkState();
|
|
||||||
if (use_simple_mcheck())
|
|
||||||
{
|
|
||||||
// remove magic constants
|
|
||||||
set_be32(b - 8, 0);
|
|
||||||
set_be32(b - 4, 0);
|
|
||||||
set_be32(b + b_size, 0);
|
|
||||||
set_be32(b + b_size + 4, 0);
|
|
||||||
//
|
|
||||||
::free(b - 16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
::free(b);
|
|
||||||
b = nullptr;
|
|
||||||
b_size = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
assert(b_size == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned width(unsigned x)
|
|
||||||
{
|
|
||||||
unsigned w = 0;
|
unsigned w = 0;
|
||||||
if ((~0u << 16) & x) { w += 16; x >>= 16; }
|
if ((~0u << 16) & x) {
|
||||||
if ((~0u << 8) & x) { w += 8; x >>= 8; }
|
w += 16;
|
||||||
if ((~0u << 4) & x) { w += 4; x >>= 4; }
|
x >>= 16;
|
||||||
if ((~0u << 2) & x) { w += 2; x >>= 2; }
|
}
|
||||||
if ((~0u << 1) & x) { w += 1; x >>= 1; }
|
if ((~0u << 8) & x) {
|
||||||
return 1+ w;
|
w += 8;
|
||||||
|
x >>= 8;
|
||||||
|
}
|
||||||
|
if ((~0u << 4) & x) {
|
||||||
|
w += 4;
|
||||||
|
x >>= 4;
|
||||||
|
}
|
||||||
|
if ((~0u << 2) & x) {
|
||||||
|
w += 2;
|
||||||
|
x >>= 2;
|
||||||
|
}
|
||||||
|
if ((~0u << 1) & x) {
|
||||||
|
w += 1;
|
||||||
|
// x >>= 1;
|
||||||
|
}
|
||||||
|
return 1 + w;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned umax(unsigned a, unsigned b)
|
static inline unsigned umax(unsigned a, unsigned b) { return (a >= b) ? a : b; }
|
||||||
{
|
|
||||||
return (a >= b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned extra)
|
unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned extra) {
|
||||||
{
|
size_t const z = uncompressed_size; // fewer keystrokes and display columns
|
||||||
size_t const z = uncompressed_size; // fewer keystrokes and display columns
|
size_t const w = umax(8, width(z - 1)); // ignore tiny offsets
|
||||||
size_t bytes = mem_size(1, z, extra);
|
size_t bytes = mem_size(1, z);
|
||||||
size_t const w = umax(8, width(z -1)); // ignore tiny offsets
|
// Worst matching: All match at max_offset, which implies 3==min_match
|
||||||
bytes = 256 + // safety?
|
// All literal: 1 bit overhead per literal byte
|
||||||
umax(bytes + z/8, // All literal: 1 bit overhead per literal byte
|
bytes = umax(bytes, bytes + z / 8);
|
||||||
// Worst matching: All match at max_offset, which implies 3==min_match
|
// NRV2B: 1 byte plus 2 bits per width exceeding 8 ("ss11")
|
||||||
// NRV2B: 1 byte plus 2 bits per width exceeding 8 ("ss11")
|
bytes = umax(bytes, (z / 3 * (8 + 2 * (w - 8) / 1)) / 8);
|
||||||
umax((z/3 * (8+ 2*(w - 8)/1))/8,
|
// NRV2E: 1 byte plus 3 bits per pair of width exceeding 7 ("ss12")
|
||||||
// NRV2E: 1 byte plus 3 bits per pair of width exceeding 7 ("ss12")
|
bytes = umax(bytes, (z / 3 * (8 + 3 * (w - 7) / 2)) / 8);
|
||||||
(z/3 * (8+ 3*(w - 7)/2))/8 ) );
|
// extra + 256 safety for rounding
|
||||||
|
bytes = mem_size(1, bytes, extra, 256);
|
||||||
return ACC_ICONV(unsigned, bytes);
|
return ACC_ICONV(unsigned, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned MemBuffer::getSizeForUncompression(unsigned uncompressed_size, unsigned extra)
|
unsigned MemBuffer::getSizeForUncompression(unsigned uncompressed_size, unsigned extra) {
|
||||||
{
|
|
||||||
size_t bytes = mem_size(1, uncompressed_size, extra);
|
size_t bytes = mem_size(1, uncompressed_size, extra);
|
||||||
// INFO: 3 bytes are the allowed overrun for the i386 asm_fast decompressors
|
|
||||||
#if (ACC_ARCH_I386)
|
|
||||||
bytes += 3;
|
|
||||||
#endif
|
|
||||||
return ACC_ICONV(unsigned, bytes);
|
return ACC_ICONV(unsigned, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemBuffer::allocForCompression(unsigned uncompressed_size, unsigned extra) {
|
||||||
void MemBuffer::allocForCompression(unsigned uncompressed_size, unsigned extra)
|
|
||||||
{
|
|
||||||
unsigned size = getSizeForCompression(uncompressed_size, extra);
|
unsigned size = getSizeForCompression(uncompressed_size, extra);
|
||||||
alloc(size);
|
alloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemBuffer::allocForUncompression(unsigned uncompressed_size, unsigned extra) {
|
||||||
void MemBuffer::allocForUncompression(unsigned uncompressed_size, unsigned extra)
|
|
||||||
{
|
|
||||||
unsigned size = getSizeForUncompression(uncompressed_size, extra);
|
unsigned size = getSizeForUncompression(uncompressed_size, extra);
|
||||||
alloc(size);
|
alloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemBuffer::fill(unsigned off, unsigned len, int value) {
|
||||||
void MemBuffer::fill(unsigned off, unsigned len, int value)
|
|
||||||
{
|
|
||||||
checkState();
|
checkState();
|
||||||
assert((int)off >= 0);
|
assert((int) off >= 0);
|
||||||
assert((int)len >= 0);
|
assert((int) len >= 0);
|
||||||
assert(off <= b_size);
|
assert(off <= b_size_in_bytes);
|
||||||
assert(len <= b_size);
|
assert(len <= b_size_in_bytes);
|
||||||
assert(off + len <= b_size);
|
assert(off + len <= b_size_in_bytes);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
memset(b + off, value, len);
|
memset(b + off, value, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#define PTR(p) ((unsigned) ((upx_uintptr_t)(p) & 0xffffffff))
|
#define PTR(p) ((unsigned) ((upx_uintptr_t)(p) &0xffffffff))
|
||||||
#define MAGIC1(p) (PTR(p) ^ 0xfefdbeeb)
|
#define MAGIC1(p) (PTR(p) ^ 0xfefdbeeb)
|
||||||
#define MAGIC2(p) (PTR(p) ^ 0xfefdbeeb ^ 0x80024001)
|
#define MAGIC2(p) (PTR(p) ^ 0xfefdbeeb ^ 0x80024001)
|
||||||
|
|
||||||
unsigned MemBuffer::global_alloc_counter = 0;
|
unsigned MemBuffer::global_alloc_counter = 0;
|
||||||
|
|
||||||
|
void MemBuffer::checkState() const {
|
||||||
void MemBuffer::checkState() const
|
|
||||||
{
|
|
||||||
if (!b)
|
if (!b)
|
||||||
throwInternalError("block not allocated");
|
throwInternalError("block not allocated");
|
||||||
if (use_simple_mcheck())
|
if (use_simple_mcheck()) {
|
||||||
{
|
|
||||||
if (get_be32(b - 4) != MAGIC1(b))
|
if (get_be32(b - 4) != MAGIC1(b))
|
||||||
throwInternalError("memory clobbered before allocated block 1");
|
throwInternalError("memory clobbered before allocated block 1");
|
||||||
if (get_be32(b - 8) != b_size)
|
if (get_be32(b - 8) != b_size_in_bytes)
|
||||||
throwInternalError("memory clobbered before allocated block 2");
|
throwInternalError("memory clobbered before allocated block 2");
|
||||||
if (get_be32(b + b_size) != MAGIC2(b))
|
if (get_be32(b + b_size_in_bytes) != MAGIC2(b))
|
||||||
throwInternalError("memory clobbered past end of allocated block");
|
throwInternalError("memory clobbered past end of allocated block");
|
||||||
}
|
}
|
||||||
assert((int)b_size > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemBuffer::alloc(upx_uint64_t size) {
|
||||||
void MemBuffer::alloc(upx_uint64_t size)
|
|
||||||
{
|
|
||||||
// NOTE: we don't automatically free a used buffer
|
// NOTE: we don't automatically free a used buffer
|
||||||
assert(b == nullptr);
|
assert(b == nullptr);
|
||||||
assert(b_size == 0);
|
assert(b_size_in_bytes == 0);
|
||||||
//
|
//
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
size_t bytes = mem_size(1, size, use_simple_mcheck() ? 32 : 0);
|
size_t bytes = mem_size(1, size, use_simple_mcheck() ? 32 : 0);
|
||||||
unsigned char *p = (unsigned char *) malloc(bytes);
|
unsigned char *p = (unsigned char *) malloc(bytes);
|
||||||
if (!p)
|
if (!p)
|
||||||
throwOutOfMemoryException();
|
throwOutOfMemoryException();
|
||||||
b_size = ACC_ICONV(unsigned, size);
|
b_size_in_bytes = ACC_ICONV(unsigned, size);
|
||||||
if (use_simple_mcheck())
|
if (use_simple_mcheck()) {
|
||||||
{
|
|
||||||
b = p + 16;
|
b = p + 16;
|
||||||
// store magic constants to detect buffer overruns
|
// store magic constants to detect buffer overruns
|
||||||
set_be32(b - 8, b_size);
|
set_be32(b - 8, b_size_in_bytes);
|
||||||
set_be32(b - 4, MAGIC1(b));
|
set_be32(b - 4, MAGIC1(b));
|
||||||
set_be32(b + b_size, MAGIC2(b));
|
set_be32(b + b_size_in_bytes, MAGIC2(b));
|
||||||
set_be32(b + b_size + 4, global_alloc_counter++);
|
set_be32(b + b_size_in_bytes + 4, global_alloc_counter++);
|
||||||
}
|
} else
|
||||||
else
|
b = p;
|
||||||
b = p ;
|
|
||||||
|
|
||||||
//fill(0, b_size, (rand() & 0xff) | 1); // debug
|
#if defined(__SANITIZE_ADDRESS__) || DEBUG
|
||||||
|
fill(0, b_size_in_bytes, (rand() & 0xff) | 1); // debug
|
||||||
|
(void) VALGRIND_MAKE_MEM_UNDEFINED(b, b_size_in_bytes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemBuffer::dealloc() {
|
||||||
|
if (b != nullptr) {
|
||||||
|
checkState();
|
||||||
|
if (use_simple_mcheck()) {
|
||||||
|
// clear magic constants
|
||||||
|
set_be32(b - 8, 0);
|
||||||
|
set_be32(b - 4, 0);
|
||||||
|
set_be32(b + b_size_in_bytes, 0);
|
||||||
|
set_be32(b + b_size_in_bytes + 4, 0);
|
||||||
|
//
|
||||||
|
::free(b - 16);
|
||||||
|
} else
|
||||||
|
::free(b);
|
||||||
|
b = nullptr;
|
||||||
|
b_size_in_bytes = 0;
|
||||||
|
} else {
|
||||||
|
assert(b_size_in_bytes == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
127
src/util/membuffer.h
Normal file
127
src/util/membuffer.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/* membuffer.h --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2022 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// A MemBuffer allocates memory on the heap, and automatically
|
||||||
|
// gets destructed when leaving scope or on exceptions.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// provides some base functionality for treating a MemBuffer as a pointer
|
||||||
|
template <class T>
|
||||||
|
class MemBufferBase {
|
||||||
|
public:
|
||||||
|
typedef T element_type;
|
||||||
|
typedef T *pointer;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
pointer b = nullptr;
|
||||||
|
unsigned b_size_in_bytes = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// NOTE: implicit conversion to underlying pointer
|
||||||
|
// NOTE: for fully bound-checked pointer use SPAN_S from xspan.h
|
||||||
|
operator pointer() const { return b; }
|
||||||
|
|
||||||
|
template <class U, class V = typename std::enable_if<std::is_integral<U>::value, U>::type>
|
||||||
|
pointer operator+(V n) const {
|
||||||
|
size_t bytes = mem_size(sizeof(T), n); // check
|
||||||
|
return raw_bytes(bytes) + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOT allowed; use raw_bytes() instead
|
||||||
|
template <class U, class V = typename std::enable_if<std::is_integral<U>::value, U>::type>
|
||||||
|
pointer operator-(V n) const = delete;
|
||||||
|
|
||||||
|
pointer raw_bytes(size_t bytes) const {
|
||||||
|
if (bytes > 0) {
|
||||||
|
assert(b != nullptr);
|
||||||
|
assert(bytes <= b_size_in_bytes);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MemBuffer : public MemBufferBase<unsigned char> {
|
||||||
|
public:
|
||||||
|
MemBuffer() = default;
|
||||||
|
explicit MemBuffer(upx_uint64_t size_in_bytes);
|
||||||
|
~MemBuffer();
|
||||||
|
|
||||||
|
static unsigned getSizeForCompression(unsigned uncompressed_size, unsigned extra = 0);
|
||||||
|
static unsigned getSizeForUncompression(unsigned uncompressed_size, unsigned extra = 0);
|
||||||
|
|
||||||
|
void alloc(upx_uint64_t size);
|
||||||
|
void allocForCompression(unsigned uncompressed_size, unsigned extra = 0);
|
||||||
|
void allocForUncompression(unsigned uncompressed_size, unsigned extra = 0);
|
||||||
|
|
||||||
|
void dealloc();
|
||||||
|
void checkState() const;
|
||||||
|
unsigned getSize() const { return b_size_in_bytes; }
|
||||||
|
|
||||||
|
// explicit converstion
|
||||||
|
void *getVoidPtr() { return (void *) b; }
|
||||||
|
const void *getVoidPtr() const { return (const void *) b; }
|
||||||
|
|
||||||
|
// util
|
||||||
|
void fill(unsigned off, unsigned len, int value);
|
||||||
|
void clear(unsigned off, unsigned len) { fill(off, len, 0); }
|
||||||
|
void clear() { fill(0, b_size_in_bytes, 0); }
|
||||||
|
|
||||||
|
// If the entire range [skip, skip+take) is inside the buffer,
|
||||||
|
// then return &b[skip]; else throwCantPack(sprintf(errfmt, skip, take)).
|
||||||
|
// This is similar to BoundedPtr, except only checks once.
|
||||||
|
// skip == offset, take == size_in_bytes
|
||||||
|
pointer subref(const char *errfmt, size_t skip, size_t take) {
|
||||||
|
return (pointer) subref_impl(errfmt, skip, take);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *subref_impl(const char *errfmt, size_t skip, size_t take);
|
||||||
|
|
||||||
|
static unsigned global_alloc_counter;
|
||||||
|
|
||||||
|
// disable copy, assignment and move assignment
|
||||||
|
MemBuffer(const MemBuffer &) = delete;
|
||||||
|
MemBuffer &operator=(const MemBuffer &) = delete;
|
||||||
|
MemBuffer &operator=(MemBuffer &&) = delete;
|
||||||
|
// disable dynamic allocation
|
||||||
|
ACC_CXX_DISABLE_NEW_DELETE
|
||||||
|
|
||||||
|
// disable taking the address => force passing by reference
|
||||||
|
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
||||||
|
MemBuffer *operator&() const = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
// raw_bytes overload
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const MemBufferBase<T> &a, size_t size_in_bytes) {
|
||||||
|
return a.raw_bytes(size_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "conf.h"
|
#include "../conf.h"
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// UPX version of string functions, with assertions and sane limits
|
// UPX version of string functions, with assertions and sane limits
|
||||||
@ -25,8 +25,9 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UPX_SNPRINTF_H
|
#pragma once
|
||||||
#define __UPX_SNPRINTF_H 1
|
#ifndef UPX_SNPRINTF_H__
|
||||||
|
#define UPX_SNPRINTF_H__ 1
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// UPX version of string functions, with assertions and sane limits
|
// UPX version of string functions, with assertions and sane limits
|
||||||
@ -35,11 +36,12 @@
|
|||||||
// info: snprintf() returns length and NOT size, but max_size is indeed size (incl NUL)
|
// info: snprintf() returns length and NOT size, but max_size is indeed size (incl NUL)
|
||||||
|
|
||||||
int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap);
|
int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap);
|
||||||
int upx_safe_snprintf (char *str, upx_rsize_t max_size, const char *format, ...) attribute_format(3, 4);
|
int upx_safe_snprintf(char *str, upx_rsize_t max_size, const char *format, ...)
|
||||||
|
attribute_format(3, 4);
|
||||||
|
|
||||||
// malloc's *ptr
|
// malloc's *ptr
|
||||||
int upx_safe_vasprintf(char **ptr, const char *format, va_list ap);
|
int upx_safe_vasprintf(char **ptr, const char *format, va_list ap);
|
||||||
int upx_safe_asprintf (char **ptr, const char *format, ...) attribute_format(2, 3);
|
int upx_safe_asprintf(char **ptr, const char *format, ...) attribute_format(2, 3);
|
||||||
|
|
||||||
// returns a malloc'd pointer
|
// returns a malloc'd pointer
|
||||||
char *upx_safe_xprintf(const char *format, ...) attribute_format(1, 2);
|
char *upx_safe_xprintf(const char *format, ...) attribute_format(1, 2);
|
||||||
@ -50,12 +52,12 @@ upx_rsize_t upx_safe_strlen(const char *);
|
|||||||
#undef snprintf
|
#undef snprintf
|
||||||
#undef sprintf
|
#undef sprintf
|
||||||
#undef vsnprintf
|
#undef vsnprintf
|
||||||
#define snprintf upx_safe_snprintf
|
#define snprintf upx_safe_snprintf
|
||||||
#define sprintf ERROR_sprintf_IS_DANGEROUS_USE_snprintf
|
#define sprintf ERROR_sprintf_IS_DANGEROUS_USE_snprintf
|
||||||
#define vsnprintf upx_safe_vsnprintf
|
#define vsnprintf upx_safe_vsnprintf
|
||||||
|
|
||||||
#undef strlen
|
#undef strlen
|
||||||
#define strlen upx_safe_strlen
|
#define strlen upx_safe_strlen
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// some unsigned char string support functions
|
// some unsigned char string support functions
|
||||||
@ -25,18 +25,18 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "conf.h"
|
#include "../conf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define ACC_WANT_ACC_INCI_H 1
|
#define ACC_WANT_ACC_INCI_H 1
|
||||||
#include "miniacc.h"
|
#include "../miniacc.h"
|
||||||
#define ACC_WANT_ACCLIB_GETOPT 1
|
#define ACC_WANT_ACCLIB_GETOPT 1
|
||||||
#define ACC_WANT_ACCLIB_HSREAD 1
|
#define ACC_WANT_ACCLIB_HSREAD 1
|
||||||
#define ACC_WANT_ACCLIB_MISC 1
|
#define ACC_WANT_ACCLIB_MISC 1
|
||||||
#define ACC_WANT_ACCLIB_VGET 1
|
#define ACC_WANT_ACCLIB_VGET 1
|
||||||
#define ACC_WANT_ACCLIB_WILDARGV 1
|
#define ACC_WANT_ACCLIB_WILDARGV 1
|
||||||
#undef HAVE_MKDIR
|
#undef HAVE_MKDIR
|
||||||
#include "miniacc.h"
|
#include "../miniacc.h"
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// assert sane memory buffer sizes to protect against integer overflows
|
// assert sane memory buffer sizes to protect against integer overflows
|
||||||
@ -51,44 +51,33 @@ ACC_COMPILE_TIME_ASSERT_HEADER(2ull * UPX_RSIZE_MAX * 9 / 8 + 16 * 1024 * 1024 <
|
|||||||
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
|
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
|
||||||
upx_uint64_t extra2) {
|
upx_uint64_t extra2) {
|
||||||
assert(element_size > 0);
|
assert(element_size > 0);
|
||||||
if (element_size > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (element_size > UPX_RSIZE_MAX)
|
||||||
throwCantPack("mem_size 1; take care");
|
throwCantPack("mem_size 1; take care");
|
||||||
if (n > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (n > UPX_RSIZE_MAX)
|
||||||
throwCantPack("mem_size 2; take care");
|
throwCantPack("mem_size 2; take care");
|
||||||
if (extra1 > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (extra1 > UPX_RSIZE_MAX)
|
||||||
throwCantPack("mem_size 3; take care");
|
throwCantPack("mem_size 3; take care");
|
||||||
if (extra2 > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (extra2 > UPX_RSIZE_MAX)
|
||||||
throwCantPack("mem_size 4; take care");
|
throwCantPack("mem_size 4; take care");
|
||||||
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
||||||
if (bytes > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (bytes > UPX_RSIZE_MAX)
|
||||||
throwCantPack("mem_size 5; take care");
|
throwCantPack("mem_size 5; take care");
|
||||||
return ACC_ICONV(upx_rsize_t, bytes);
|
return ACC_ICONV(upx_rsize_t, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n) {
|
|
||||||
mem_size_assert(element_size, n);
|
|
||||||
return ACC_ICONV(upx_rsize_t, n); // return n
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
|
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
|
||||||
upx_uint64_t extra2) {
|
upx_uint64_t extra2) noexcept {
|
||||||
assert(element_size > 0);
|
assert(element_size > 0);
|
||||||
if (element_size > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (element_size > UPX_RSIZE_MAX)
|
||||||
return false;
|
return false;
|
||||||
if (n > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (n > UPX_RSIZE_MAX)
|
||||||
return false;
|
return false;
|
||||||
if (extra1 > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (extra1 > UPX_RSIZE_MAX)
|
||||||
return false;
|
return false;
|
||||||
if (extra2 > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (extra2 > UPX_RSIZE_MAX)
|
||||||
return false;
|
return false;
|
||||||
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
||||||
if (bytes > UPX_RSIZE_MAX)
|
if __acc_very_unlikely (bytes > UPX_RSIZE_MAX)
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mem_size_valid_bytes(upx_uint64_t bytes) {
|
|
||||||
if (bytes > UPX_RSIZE_MAX)
|
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -100,28 +89,49 @@ TEST_CASE("mem_size") {
|
|||||||
CHECK(!mem_size_valid(1, 0x30000000, 1));
|
CHECK(!mem_size_valid(1, 0x30000000, 1));
|
||||||
CHECK(!mem_size_valid(1, 0x30000000, 0, 1));
|
CHECK(!mem_size_valid(1, 0x30000000, 0, 1));
|
||||||
CHECK(!mem_size_valid(1, 0x30000000, 0x30000000, 0x30000000));
|
CHECK(!mem_size_valid(1, 0x30000000, 0x30000000, 0x30000000));
|
||||||
|
CHECK_NOTHROW(mem_size(1, 0));
|
||||||
|
CHECK_NOTHROW(mem_size(1, 0x30000000));
|
||||||
|
CHECK_THROWS(mem_size(1, 0x30000000 + 1));
|
||||||
|
CHECK_THROWS(mem_size(1, 0x30000000, 1));
|
||||||
|
CHECK_THROWS(mem_size(1, 0x30000000, 0, 1));
|
||||||
|
CHECK_THROWS(mem_size(1, 0x30000000, 0x30000000, 0x30000000));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ptr_diff(const void *p1, const void *p2) {
|
int ptr_diff_bytes(const void *a, const void *b) {
|
||||||
assert(p1 != nullptr);
|
if __acc_very_unlikely (a == nullptr) {
|
||||||
assert(p2 != nullptr);
|
throwCantPack("ptr_diff_bytes null 1; take care");
|
||||||
ptrdiff_t d = (const char *) p1 - (const char *) p2;
|
}
|
||||||
if (p1 >= p2)
|
if __acc_very_unlikely (b == nullptr) {
|
||||||
assert(mem_size_valid_bytes(d));
|
throwCantPack("ptr_diff_bytes null 2; take care");
|
||||||
else
|
}
|
||||||
assert(mem_size_valid_bytes(-d));
|
ptrdiff_t d = (const char *) a - (const char *) b;
|
||||||
|
if (a >= b) {
|
||||||
|
if __acc_very_unlikely (!mem_size_valid_bytes(d))
|
||||||
|
throwCantPack("ptr_diff_bytes 1; take care");
|
||||||
|
} else {
|
||||||
|
if __acc_very_unlikely (!mem_size_valid_bytes(-d))
|
||||||
|
throwCantPack("ptr_diff_bytes 2; take care");
|
||||||
|
}
|
||||||
return ACC_ICONV(int, d);
|
return ACC_ICONV(int, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ptr_udiff(const void *p1, const void *p2) {
|
unsigned ptr_udiff_bytes(const void *a, const void *b) {
|
||||||
int d = ptr_diff(p1, p2);
|
int d = ptr_diff_bytes(a, b);
|
||||||
assert(d >= 0);
|
if __acc_very_unlikely (d < 0)
|
||||||
|
throwCantPack("ptr_udiff_bytes; take care");
|
||||||
return ACC_ICONV(unsigned, d);
|
return ACC_ICONV(unsigned, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_clear(void *p, size_t n) {
|
TEST_CASE("ptr_diff") {
|
||||||
mem_size_assert(1, n);
|
char buf[4] = {0, 1, 2, 3};
|
||||||
memset(p, 0, n);
|
CHECK_THROWS(ptr_diff_bytes(nullptr, buf));
|
||||||
|
CHECK_THROWS(ptr_diff_bytes(buf, nullptr));
|
||||||
|
CHECK(ptr_diff(buf, buf) == 0);
|
||||||
|
CHECK(ptr_diff(buf + 1, buf) == 1);
|
||||||
|
CHECK(ptr_diff(buf, buf + 1) == -1);
|
||||||
|
CHECK(ptr_udiff(buf, buf) == 0);
|
||||||
|
CHECK(ptr_udiff(buf + 1, buf) == 1);
|
||||||
|
CHECK_THROWS(ptr_udiff(buf, buf + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -560,6 +570,9 @@ TEST_CASE("get_ratio") {
|
|||||||
CHECK(get_ratio(1, 11) == 9999999);
|
CHECK(get_ratio(1, 11) == 9999999);
|
||||||
CHECK(get_ratio(100000, 100000) == 1000050);
|
CHECK(get_ratio(100000, 100000) == 1000050);
|
||||||
CHECK(get_ratio(100000, 200000) == 2000050);
|
CHECK(get_ratio(100000, 200000) == 2000050);
|
||||||
|
CHECK(get_ratio(UPX_RSIZE_MAX, UPX_RSIZE_MAX) == 1000050);
|
||||||
|
CHECK(get_ratio(2 * UPX_RSIZE_MAX, 2 * UPX_RSIZE_MAX) == 1000050);
|
||||||
|
CHECK(get_ratio(2 * UPX_RSIZE_MAX, 1024ull * UPX_RSIZE_MAX) == 9999999);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
@ -25,32 +25,72 @@
|
|||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UPX_UTIL_H
|
#pragma once
|
||||||
#define __UPX_UTIL_H 1
|
#ifndef UPX_UTIL_H__
|
||||||
|
#define UPX_UTIL_H__ 1
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// protect against integer overflows and malicious header fields
|
// assert sane memory buffer sizes to protect against integer overflows
|
||||||
|
// and malicious header fields
|
||||||
|
// see C 11 standard, Annex K
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#define New(type, n) new type[mem_size_get_n(sizeof(type), n)]
|
inline bool mem_size_valid_bytes(upx_uint64_t bytes) noexcept { return bytes <= UPX_RSIZE_MAX; }
|
||||||
|
|
||||||
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
|
||||||
upx_uint64_t extra2 = 0);
|
|
||||||
upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n);
|
|
||||||
|
|
||||||
inline void mem_size_assert(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
|
||||||
upx_uint64_t extra2 = 0) {
|
|
||||||
(void) mem_size(element_size, n, extra1, extra2); // sanity check
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
||||||
upx_uint64_t extra2 = 0);
|
upx_uint64_t extra2 = 0) noexcept;
|
||||||
bool mem_size_valid_bytes(upx_uint64_t bytes);
|
|
||||||
|
|
||||||
int ptr_diff(const void *p1, const void *p2);
|
// new with asserted size; will throw on failure
|
||||||
unsigned ptr_udiff(const void *p1, const void *p2); // asserts p1 >= p2
|
#define New(type, n) new type[mem_size_get_n(sizeof(type), n)]
|
||||||
|
|
||||||
void mem_clear(void *p, size_t n);
|
// will throw on invalid size
|
||||||
|
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
|
||||||
|
upx_uint64_t extra2 = 0);
|
||||||
|
|
||||||
|
// inline fast paths:
|
||||||
|
|
||||||
|
// will throw on invalid size
|
||||||
|
inline upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n) {
|
||||||
|
upx_uint64_t bytes = element_size * n;
|
||||||
|
if __acc_very_unlikely (element_size == 0 || element_size > UPX_RSIZE_MAX ||
|
||||||
|
n > UPX_RSIZE_MAX || bytes > UPX_RSIZE_MAX)
|
||||||
|
return mem_size(element_size, n, 0, 0); // this will throw
|
||||||
|
return ACC_ICONV(upx_rsize_t, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// will throw on invalid size
|
||||||
|
inline upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n) {
|
||||||
|
(void) mem_size(element_size, n); // assert size
|
||||||
|
return ACC_ICONV(upx_rsize_t, n); // and return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// will throw on invalid size
|
||||||
|
inline void mem_size_assert(upx_uint64_t element_size, upx_uint64_t n) {
|
||||||
|
(void) mem_size(element_size, n); // assert size
|
||||||
|
}
|
||||||
|
|
||||||
|
// will throw on invalid size
|
||||||
|
inline void mem_clear(void *p, size_t n) {
|
||||||
|
(void) mem_size(1, n); // assert size
|
||||||
|
memset(p, 0, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ptrdiff_t with nullptr check and asserted size; will throw on failure
|
||||||
|
// WARNING: returns size_in_bytes, not number of elements!
|
||||||
|
int ptr_diff_bytes(const void *a, const void *b);
|
||||||
|
unsigned ptr_udiff_bytes(const void *a, const void *b); // asserts a >= b
|
||||||
|
|
||||||
|
// short names "ptr_diff" and "ptr_udiff" for types with sizeof(X) == 1
|
||||||
|
template <class T, class U>
|
||||||
|
inline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, int>::type ptr_diff(const T *a,
|
||||||
|
const U *b) {
|
||||||
|
return ptr_diff_bytes(a, b);
|
||||||
|
}
|
||||||
|
template <class T, class U>
|
||||||
|
inline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, unsigned>::type
|
||||||
|
ptr_udiff(const T *a, const U *b) {
|
||||||
|
return ptr_udiff_bytes(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// misc. support functions
|
// misc. support functions
|
||||||
637
src/util/xspan.cpp
Normal file
637
src/util/xspan.cpp
Normal file
@ -0,0 +1,637 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../conf.h"
|
||||||
|
|
||||||
|
#if WITH_SPAN
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
unsigned long long span_check_stats_check_range;
|
||||||
|
|
||||||
|
__acc_noinline void span_fail_nullptr() {
|
||||||
|
throwCantUnpack("span unexpected NULL pointer; take care!");
|
||||||
|
}
|
||||||
|
|
||||||
|
__acc_noinline void span_fail_not_same_base() {
|
||||||
|
throwInternalError("span unexpected base pointer; take care!");
|
||||||
|
}
|
||||||
|
|
||||||
|
__acc_noinline void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes) {
|
||||||
|
if __acc_very_unlikely (p == nullptr)
|
||||||
|
throwCantUnpack("span_check_range: unexpected NULL pointer; take care!");
|
||||||
|
if __acc_very_unlikely (base == nullptr)
|
||||||
|
throwCantUnpack("span_check_range: unexpected NULL base; take care!");
|
||||||
|
ptrdiff_t off = (const char *) p - (const char *) base;
|
||||||
|
if __acc_very_unlikely (off < 0 || off > size_in_bytes)
|
||||||
|
throwCantUnpack("span_check_range: pointer out of range; take care!");
|
||||||
|
span_check_stats_check_range += 1;
|
||||||
|
// fprintf(stderr, "span_check_range done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // WITH_SPAN
|
||||||
|
#if WITH_SPAN >= 2
|
||||||
|
|
||||||
|
// lots of tests (and probably quite a number of redundant tests)
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpanOrNull") {
|
||||||
|
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||||
|
char *base_buf = real_buf + 2;
|
||||||
|
char *const my_null = nullptr;
|
||||||
|
typedef PtrOrSpanOrNull<char> Span0;
|
||||||
|
|
||||||
|
// basic nullptr
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = my_null);
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf).assign(my_null));
|
||||||
|
// basic range checking
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 0, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 0, base_buf) - 0);
|
||||||
|
CHECK_THROWS(Span0(base_buf, 0, base_buf) + 1);
|
||||||
|
CHECK_THROWS(Span0(base_buf, 0, base_buf) - 1);
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) + 4);
|
||||||
|
CHECK_THROWS(Span0(base_buf, 4, base_buf) + 5);
|
||||||
|
CHECK_THROWS(Span0(base_buf - 1, 4, base_buf));
|
||||||
|
CHECK_THROWS(Span0(base_buf + 1, 0, base_buf));
|
||||||
|
// basic same base
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 1, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 5, base_buf));
|
||||||
|
CHECK_THROWS(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf + 1));
|
||||||
|
|
||||||
|
Span0 a1(nullptr);
|
||||||
|
assert(a1 == nullptr);
|
||||||
|
assert(a1.raw_ptr() == nullptr);
|
||||||
|
assert(a1.raw_base() == nullptr);
|
||||||
|
assert(a1.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1[0]);
|
||||||
|
|
||||||
|
Span0 a2 = nullptr;
|
||||||
|
assert(a2 == nullptr);
|
||||||
|
assert(a2.raw_ptr() == nullptr);
|
||||||
|
assert(a2.raw_base() == nullptr);
|
||||||
|
assert(a2.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*a2);
|
||||||
|
CHECK_THROWS(a2[0]);
|
||||||
|
|
||||||
|
Span0 base0(nullptr, 4, base_buf);
|
||||||
|
assert(base0.raw_ptr() == nullptr);
|
||||||
|
assert(base0.raw_base() == base_buf);
|
||||||
|
assert(base0.raw_size_in_bytes() == 4u);
|
||||||
|
CHECK_THROWS(*base0); // nullptr
|
||||||
|
CHECK_THROWS(base0[0]); // nullptr
|
||||||
|
CHECK_THROWS(base0 + 1); // nullptr
|
||||||
|
|
||||||
|
Span0 base4(base_buf, 4);
|
||||||
|
assert(base4.raw_ptr() == base_buf);
|
||||||
|
assert(base4.raw_base() == base_buf);
|
||||||
|
assert(base4.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base0;
|
||||||
|
assert(a1 == nullptr);
|
||||||
|
assert(a1.raw_ptr() == nullptr);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
a1 = base4;
|
||||||
|
assert(a1 == base_buf);
|
||||||
|
assert(a1.raw_ptr() == base_buf);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
assert(a1 != nullptr);
|
||||||
|
a1 = base_buf + 1;
|
||||||
|
CHECK(*a1++ == 1);
|
||||||
|
CHECK(*++a1 == 3);
|
||||||
|
CHECK(*a1 == 3);
|
||||||
|
a1 = base_buf + 4; // at the end of buffer
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||||
|
assert(a1 == base_buf + 4);
|
||||||
|
CHECK(a1[-4] == 0);
|
||||||
|
CHECK_THROWS(a1[-5]); // range error
|
||||||
|
a1 = base_buf;
|
||||||
|
CHECK(*a1 == 0);
|
||||||
|
|
||||||
|
Span0 new_base4(base_buf + 2, 4);
|
||||||
|
CHECK_THROWS(a1 = new_base4); // not same base
|
||||||
|
a2 = new_base4;
|
||||||
|
CHECK_THROWS(a2 = base4); // not same base
|
||||||
|
|
||||||
|
Span0 s0_no_base(nullptr);
|
||||||
|
Span0 s0_with_base(nullptr, 4, base_buf);
|
||||||
|
s0_no_base = nullptr;
|
||||||
|
s0_with_base = nullptr;
|
||||||
|
s0_with_base = s0_no_base;
|
||||||
|
assert(s0_no_base.raw_base() == nullptr);
|
||||||
|
assert(s0_with_base.raw_base() == base_buf);
|
||||||
|
s0_no_base = s0_with_base;
|
||||||
|
assert(s0_no_base.raw_base() == base_buf);
|
||||||
|
assert(s0_no_base.raw_ptr() == nullptr);
|
||||||
|
assert(s0_with_base.raw_ptr() == nullptr);
|
||||||
|
s0_no_base = my_null;
|
||||||
|
s0_with_base = my_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan") {
|
||||||
|
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||||
|
char *base_buf = real_buf + 2;
|
||||||
|
char *const my_null = nullptr;
|
||||||
|
typedef PtrOrSpan<char> SpanP;
|
||||||
|
|
||||||
|
// basic nullptr
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = my_null);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf).assign(my_null));
|
||||||
|
// basic range checking
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf) - 0);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 0, base_buf) + 1);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 0, base_buf) - 1);
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) + 4);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf) + 5);
|
||||||
|
CHECK_THROWS(SpanP(base_buf - 1, 4, base_buf));
|
||||||
|
CHECK_THROWS(SpanP(base_buf + 1, 0, base_buf));
|
||||||
|
// basic same base
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 1, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 5, base_buf));
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf + 1));
|
||||||
|
|
||||||
|
SpanP x1(base_buf, 0);
|
||||||
|
assert(x1 != nullptr);
|
||||||
|
assert(x1.raw_ptr() == base_buf);
|
||||||
|
assert(x1.raw_base() == base_buf);
|
||||||
|
assert(x1.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*x1);
|
||||||
|
CHECK_THROWS(x1[0]);
|
||||||
|
|
||||||
|
SpanP a2 = base_buf;
|
||||||
|
assert(a2 != nullptr);
|
||||||
|
assert(a2.raw_ptr() == base_buf);
|
||||||
|
assert(a2.raw_base() == nullptr);
|
||||||
|
assert(a2.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK(*a2 == 0);
|
||||||
|
CHECK(a2[1] == 1);
|
||||||
|
|
||||||
|
SpanP base0(base_buf, 4, base_buf);
|
||||||
|
assert(base0.raw_ptr() == base_buf);
|
||||||
|
assert(base0.raw_base() == base_buf);
|
||||||
|
assert(base0.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanP base4(base_buf, 4);
|
||||||
|
assert(base4.raw_ptr() == base_buf);
|
||||||
|
assert(base4.raw_base() == base_buf);
|
||||||
|
assert(base4.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanP a1(base_buf, 4);
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base0;
|
||||||
|
assert(a1 == base0);
|
||||||
|
assert(a1 != nullptr);
|
||||||
|
assert(a1.raw_ptr() == base0.raw_ptr());
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
a1 = base4;
|
||||||
|
assert(a1 == base_buf);
|
||||||
|
assert(a1.raw_ptr() == base_buf);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base_buf + 1;
|
||||||
|
CHECK(*a1++ == 1);
|
||||||
|
CHECK(*++a1 == 3);
|
||||||
|
CHECK(*a1 == 3);
|
||||||
|
a1 = base_buf + 4; // at the end of buffer
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||||
|
assert(a1 == base_buf + 4);
|
||||||
|
CHECK(a1[-4] == 0);
|
||||||
|
CHECK_THROWS(a1[-5]); // range error
|
||||||
|
a1 = base_buf;
|
||||||
|
CHECK(*a1 == 0);
|
||||||
|
|
||||||
|
SpanP new_base4(base_buf + 2, 4);
|
||||||
|
CHECK_THROWS(a1 = new_base4); // not same base
|
||||||
|
a2 = new_base4;
|
||||||
|
CHECK_THROWS(a2 = base4); // not same base
|
||||||
|
|
||||||
|
SpanP sp_no_base(base_buf);
|
||||||
|
SpanP sp_with_base(base_buf, 4, base_buf);
|
||||||
|
assert(sp_no_base.raw_base() == nullptr);
|
||||||
|
assert(sp_with_base.raw_base() == base_buf);
|
||||||
|
CHECK_THROWS(sp_no_base = my_null); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_with_base = my_null); // nullptr assignment
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
typedef PtrOrSpanOrNull<char> Span0;
|
||||||
|
Span0 s0_no_base(nullptr);
|
||||||
|
Span0 s0_with_base(nullptr, 4, base_buf);
|
||||||
|
CHECK_THROWS(sp_no_base = s0_no_base); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_no_base = s0_with_base); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_with_base = s0_no_base); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_with_base = s0_with_base); // nullptr assignment
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("Span") {
|
||||||
|
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||||
|
char *base_buf = real_buf + 2;
|
||||||
|
char *const my_null = nullptr;
|
||||||
|
typedef Span<char> SpanS;
|
||||||
|
|
||||||
|
// basic nullptr
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = my_null);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf).assign(my_null));
|
||||||
|
// basic range checking
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf) - 0);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 0, base_buf) + 1);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 0, base_buf) - 1);
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) + 4);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf) + 5);
|
||||||
|
CHECK_THROWS(SpanS(base_buf - 1, 4, base_buf));
|
||||||
|
CHECK_THROWS(SpanS(base_buf + 1, 0, base_buf));
|
||||||
|
// basic same base
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 1, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 5, base_buf));
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf + 1));
|
||||||
|
|
||||||
|
SpanS x1(base_buf, 0);
|
||||||
|
assert(x1 != nullptr);
|
||||||
|
assert(x1.raw_ptr() == base_buf);
|
||||||
|
assert(x1.raw_base() == base_buf);
|
||||||
|
assert(x1.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*x1);
|
||||||
|
CHECK_THROWS(x1[0]);
|
||||||
|
|
||||||
|
SpanS a2(base_buf, 4);
|
||||||
|
assert(a2 != nullptr);
|
||||||
|
assert(a2.raw_ptr() == base_buf);
|
||||||
|
assert(a2.raw_base() == base_buf);
|
||||||
|
assert(a2.raw_size_in_bytes() == 4u);
|
||||||
|
CHECK(*a2 == 0);
|
||||||
|
CHECK(a2[1] == 1);
|
||||||
|
|
||||||
|
SpanS base0(base_buf, 4, base_buf);
|
||||||
|
assert(base0.raw_ptr() == base_buf);
|
||||||
|
assert(base0.raw_base() == base_buf);
|
||||||
|
assert(base0.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanS base4(base_buf, 4);
|
||||||
|
assert(base4.raw_ptr() == base_buf);
|
||||||
|
assert(base4.raw_base() == base_buf);
|
||||||
|
assert(base4.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanS a1(base_buf, 4);
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base0;
|
||||||
|
assert(a1 == base0);
|
||||||
|
assert(a1 != nullptr);
|
||||||
|
assert(a1.raw_ptr() == base0.raw_ptr());
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
a1 = base4;
|
||||||
|
assert(a1 == base_buf);
|
||||||
|
assert(a1.raw_ptr() == base_buf);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base_buf + 1;
|
||||||
|
CHECK(*a1++ == 1);
|
||||||
|
CHECK(*++a1 == 3);
|
||||||
|
CHECK(*a1 == 3);
|
||||||
|
a1 = base_buf + 4; // at the end of buffer
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||||
|
assert(a1 == base_buf + 4);
|
||||||
|
CHECK(a1[-4] == 0);
|
||||||
|
CHECK_THROWS(a1[-5]); // range error
|
||||||
|
a1 = base_buf;
|
||||||
|
CHECK(*a1 == 0);
|
||||||
|
|
||||||
|
SpanS new_base4(base_buf + 2, 4);
|
||||||
|
CHECK_THROWS(a1 = new_base4); // not same base
|
||||||
|
CHECK_THROWS(a2 = new_base4); // not same base
|
||||||
|
|
||||||
|
SpanS ss_with_base(base_buf, 4, base_buf);
|
||||||
|
assert(ss_with_base.raw_base() == base_buf);
|
||||||
|
CHECK_THROWS(ss_with_base = my_null); // nullptr assignment
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
typedef PtrOrSpanOrNull<char> Span0;
|
||||||
|
Span0 s0_no_base(nullptr);
|
||||||
|
Span0 s0_with_base(nullptr, 4, base_buf);
|
||||||
|
CHECK_THROWS(ss_with_base = s0_no_base); // nullptr assignment
|
||||||
|
CHECK_THROWS(ss_with_base = s0_with_base); // nullptr assignment
|
||||||
|
typedef PtrOrSpanOrNull<char> SpanP;
|
||||||
|
SpanP sp_1(base_buf + 1, 3, base_buf);
|
||||||
|
SpanP sp_2(base_buf + 2, 2, base_buf);
|
||||||
|
// SpanP sp_4(base_buf + 4, 0, base_buf);
|
||||||
|
SpanP sp_x(base_buf + 1, 3, base_buf + 1);
|
||||||
|
assert(ss_with_base.raw_base() == base_buf);
|
||||||
|
#if 0
|
||||||
|
ss_with_base = sp_1;
|
||||||
|
assert(ss_with_base.raw_ptr() == base_buf + 1);
|
||||||
|
CHECK(*ss_with_base == 1);
|
||||||
|
ss_with_base = sp_2;
|
||||||
|
assert(ss_with_base.raw_ptr() == base_buf + 2);
|
||||||
|
CHECK_THROWS(ss_with_base = sp_x); // not same base
|
||||||
|
assert(ss_with_base.raw_base() == base_buf);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("Span void ptr") {
|
||||||
|
static char a[4] = {0, 1, 2, 3};
|
||||||
|
SPAN_0(void) a0(a, 4);
|
||||||
|
SPAN_P(void) ap(a, 4);
|
||||||
|
SPAN_S(void) as(a, 4);
|
||||||
|
SPAN_0(const void) c0(a, 4);
|
||||||
|
SPAN_P(const void) cp(a, 4);
|
||||||
|
SPAN_S(const void) cs(a, 4);
|
||||||
|
static const char b[4] = {0, 1, 2, 3};
|
||||||
|
SPAN_0(const void) b0(b, 4);
|
||||||
|
SPAN_P(const void) bp(b, 4);
|
||||||
|
SPAN_S(const void) bs(b, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Span deref/array/arrow") {
|
||||||
|
static char real_a[2 + 4 + 2] = {126, 127, 0, 1, 2, 3, 124, 125};
|
||||||
|
static char *a = real_a + 2;
|
||||||
|
SPAN_0(char) a0(a, 4);
|
||||||
|
SPAN_P(char) ap(a, 4);
|
||||||
|
SPAN_S(char) as(a, 4);
|
||||||
|
CHECK_THROWS(a0[4]);
|
||||||
|
CHECK_THROWS(a0[-1]);
|
||||||
|
CHECK_THROWS(a0[-2]);
|
||||||
|
a0 += 2;
|
||||||
|
CHECK(*a0 == 2);
|
||||||
|
CHECK(a0[-1] == 1);
|
||||||
|
CHECK(a0[0] == 2);
|
||||||
|
CHECK(a0[1] == 3);
|
||||||
|
ap += 2;
|
||||||
|
CHECK(*ap == 2);
|
||||||
|
CHECK(ap[-1] == 1);
|
||||||
|
CHECK(ap[0] == 2);
|
||||||
|
CHECK(ap[1] == 3);
|
||||||
|
as += 2;
|
||||||
|
CHECK(*as == 2);
|
||||||
|
CHECK(as[-1] == 1);
|
||||||
|
CHECK(as[0] == 2);
|
||||||
|
CHECK(as[1] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Span subspan") {
|
||||||
|
static char buf[4] = {0, 1, 2, 3};
|
||||||
|
SPAN_S(char) as(buf, 4);
|
||||||
|
CHECK(as.subspan(1, 1)[0] == 1);
|
||||||
|
CHECK((as + 1).subspan(1, 1)[0] == 2);
|
||||||
|
CHECK((as + 2).subspan(0, -2)[0] == 0);
|
||||||
|
CHECK_THROWS(as.subspan(1, 0)[0]);
|
||||||
|
CHECK_THROWS(as.subspan(1, 1)[-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Span constness") {
|
||||||
|
static char buf[4] = {0, 1, 2, 3};
|
||||||
|
|
||||||
|
SPAN_0(char) b0(buf, 4);
|
||||||
|
SPAN_P(char) bp(buf, 4);
|
||||||
|
SPAN_S(char) bs(buf, 4);
|
||||||
|
|
||||||
|
SPAN_0(char) s0(b0);
|
||||||
|
SPAN_P(char) sp(bp);
|
||||||
|
SPAN_S(char) ss(bs);
|
||||||
|
|
||||||
|
SPAN_0(const char) b0c(buf, 4);
|
||||||
|
SPAN_P(const char) bpc(buf, 4);
|
||||||
|
SPAN_S(const char) bsc(buf, 4);
|
||||||
|
|
||||||
|
SPAN_0(const char) s0c(b0c);
|
||||||
|
SPAN_P(const char) spc(bpc);
|
||||||
|
SPAN_S(const char) ssc(bsc);
|
||||||
|
|
||||||
|
SPAN_0(const char) x0c(b0);
|
||||||
|
SPAN_P(const char) xpc(bp);
|
||||||
|
SPAN_S(const char) xsc(bs);
|
||||||
|
|
||||||
|
CHECK(ptr_diff_bytes(b0, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(bp, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(s0, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(sp, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
||||||
|
//
|
||||||
|
CHECK(ptr_diff_bytes(s0, bp) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(s0, sp) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(s0, ss) == 0);
|
||||||
|
//
|
||||||
|
CHECK(ptr_diff_bytes(s0c, b0c) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(spc, bpc) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(ssc, bsc) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int my_memcmp_v1(SPAN_P(const void) a, SPAN_0(const void) b, size_t n) {
|
||||||
|
if (b == nullptr)
|
||||||
|
return -2;
|
||||||
|
SPAN_0(const void) x(a);
|
||||||
|
return memcmp(x, b, n);
|
||||||
|
}
|
||||||
|
int my_memcmp_v2(SPAN_P(const char) a, SPAN_0(const char) b, size_t n) {
|
||||||
|
if (a == b)
|
||||||
|
return 0;
|
||||||
|
if (b == nullptr)
|
||||||
|
return -2;
|
||||||
|
a += 1;
|
||||||
|
b -= 1;
|
||||||
|
SPAN_0(const char) x(a);
|
||||||
|
SPAN_0(const char) y = b;
|
||||||
|
return memcmp(x, y, n);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan") {
|
||||||
|
static const char buf[4] = {0, 1, 2, 3};
|
||||||
|
CHECK(my_memcmp_v1(buf, nullptr, 4) == -2);
|
||||||
|
CHECK(my_memcmp_v2(buf + 4, buf + 4, 999) == 0);
|
||||||
|
CHECK(my_memcmp_v2(buf, buf + 2, 3) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan char") {
|
||||||
|
char real_buf[2 + 8 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 6, 7, 124, 125};
|
||||||
|
char *buf = real_buf + 2;
|
||||||
|
SPAN_P(char) a(buf, SpanSizeInBytes(8));
|
||||||
|
SPAN_P(char) b = a.subspan(0, 7);
|
||||||
|
SPAN_P(char) c = (b + 1).subspan(0, 6);
|
||||||
|
a += 1;
|
||||||
|
CHECK(*a == 1);
|
||||||
|
*a++ += 1;
|
||||||
|
*b++ = 1;
|
||||||
|
CHECK(a == buf + 2);
|
||||||
|
CHECK(b == buf + 1);
|
||||||
|
CHECK(c == buf + 1);
|
||||||
|
CHECK(*b == 2);
|
||||||
|
CHECK(*c == 2);
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8u);
|
||||||
|
CHECK(b.raw_size_in_bytes() == 7u);
|
||||||
|
CHECK(c.raw_size_in_bytes() == 6u);
|
||||||
|
CHECK(a.raw_base() == buf);
|
||||||
|
CHECK(b.raw_base() == buf);
|
||||||
|
CHECK(c.raw_base() == buf + 1);
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(get_le32(a) != 0);
|
||||||
|
#endif
|
||||||
|
++c;
|
||||||
|
c++;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(get_le32(c) != 0);
|
||||||
|
#endif
|
||||||
|
++c;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK_THROWS(get_le32(c));
|
||||||
|
#endif
|
||||||
|
++b;
|
||||||
|
b++;
|
||||||
|
b += 4;
|
||||||
|
CHECK(b.raw_ptr() == buf + 7);
|
||||||
|
CHECK_THROWS(*b);
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8u);
|
||||||
|
a = b;
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8u);
|
||||||
|
CHECK(a.raw_ptr() == buf + 7);
|
||||||
|
a++;
|
||||||
|
CHECK_THROWS(*a);
|
||||||
|
CHECK_THROWS(raw_bytes(a, 1));
|
||||||
|
a = b;
|
||||||
|
CHECK_THROWS(a = c);
|
||||||
|
*a = 0;
|
||||||
|
a = buf;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(upx_safe_strlen(a) == 7u);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan int") {
|
||||||
|
int buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
|
SPAN_P(int) a(buf, SpanCount(8));
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8 * sizeof(int));
|
||||||
|
SPAN_P(int) b = a.subspan(0, 7);
|
||||||
|
CHECK(b.raw_size_in_bytes() == 7 * sizeof(int));
|
||||||
|
SPAN_P(int) c = (b + 1).subspan(0, 6);
|
||||||
|
CHECK(c.raw_size_in_bytes() == 6 * sizeof(int));
|
||||||
|
a += 1;
|
||||||
|
CHECK(*a == 1);
|
||||||
|
CHECK(*a++ == 1);
|
||||||
|
CHECK(*++a == 3);
|
||||||
|
CHECK(--*a == 2);
|
||||||
|
CHECK(*a-- == 2);
|
||||||
|
CHECK(*b == 0);
|
||||||
|
CHECK(*c == 1);
|
||||||
|
a = buf + 7;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(get_le32(a) == ne32_to_le32(7));
|
||||||
|
#endif
|
||||||
|
a++;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK_THROWS(get_le32(a));
|
||||||
|
#endif
|
||||||
|
CHECK_THROWS(raw_bytes(a, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// codegen
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <class T>
|
||||||
|
__acc_static_noinline int foo(T p) {
|
||||||
|
unsigned r = 0;
|
||||||
|
r += *p++;
|
||||||
|
r += *++p;
|
||||||
|
p += 3;
|
||||||
|
r += *p;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
SPAN_0(T)
|
||||||
|
make_span_0(T *ptr, size_t count) {
|
||||||
|
return PtrOrSpanOrNull<T>(ptr, count);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
SPAN_P(T)
|
||||||
|
make_span_p(T *ptr, size_t count) {
|
||||||
|
return PtrOrSpan<T>(ptr, count);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
SPAN_S(T)
|
||||||
|
make_span_s(T *ptr, size_t count) {
|
||||||
|
return Span<T>(ptr, count);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("Span codegen") {
|
||||||
|
char buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
|
CHECK(foo(buf) == 0 + 2 + 5);
|
||||||
|
CHECK(foo(make_span_0(buf, 8)) == 0 + 2 + 5);
|
||||||
|
CHECK(foo(make_span_p(buf, 8)) == 0 + 2 + 5);
|
||||||
|
CHECK(foo(make_span_s(buf, 8)) == 0 + 2 + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WITH_SPAN >= 2
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
144
src/util/xspan.h
Normal file
144
src/util/xspan.h
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// config and implementation
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef WITH_SPAN
|
||||||
|
#define WITH_SPAN 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WITH_SPAN
|
||||||
|
|
||||||
|
// automatic conversion to underlying pointer; do NOT enable this config as this
|
||||||
|
// defeats the main purpose of a checked pointer => use raw_bytes() as needed;
|
||||||
|
// and see xspan_fwd.h how to make this more convenient
|
||||||
|
#ifndef SPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION
|
||||||
|
#define SPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION 0
|
||||||
|
#endif
|
||||||
|
// allow automatic conversion PtrOrSpanOrNull => PtrOrSpan => Span (with runtime checks)
|
||||||
|
// choose between compile-time safety vs. possible run-time errors
|
||||||
|
#ifndef SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
#define SPAN_CONFIG_ENABLE_SPAN_CONVERSION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "xspan_impl.h"
|
||||||
|
|
||||||
|
#ifdef SPAN_NAMESPACE_NAME
|
||||||
|
// help constructor to distinguish between number of elements and bytes
|
||||||
|
using SPAN_NAMESPACE_NAME::SpanCount;
|
||||||
|
using SPAN_NAMESPACE_NAME::SpanSizeInBytes;
|
||||||
|
// actual classes
|
||||||
|
using SPAN_NAMESPACE_NAME::Ptr;
|
||||||
|
using SPAN_NAMESPACE_NAME::PtrOrSpan;
|
||||||
|
using SPAN_NAMESPACE_NAME::PtrOrSpanOrNull;
|
||||||
|
using SPAN_NAMESPACE_NAME::Span;
|
||||||
|
// util
|
||||||
|
using SPAN_NAMESPACE_NAME::raw_bytes; // overloaded for all classes
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WITH_SPAN
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// usage
|
||||||
|
//
|
||||||
|
// PtrOrSpanOrNull invariants: ptr is checked if ptr != null && base != null
|
||||||
|
// PtrOrSpan invariants: ptr is checked if base != null; ptr != null
|
||||||
|
// Span invariants: ptr is checked; ptr != null; base != null
|
||||||
|
//
|
||||||
|
// Ptr invariants: none; this is just a no-op pointer wrapper
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if WITH_SPAN >= 2
|
||||||
|
|
||||||
|
// fully checked
|
||||||
|
|
||||||
|
#define SPAN_0(type) PtrOrSpanOrNull<type>
|
||||||
|
#define SPAN_P(type) PtrOrSpan<type>
|
||||||
|
#define SPAN_S(type) Span<type>
|
||||||
|
|
||||||
|
// define a new variable
|
||||||
|
#define SPAN_0_VAR(type, var, first, ...) SPAN_0(type) var(first, ##__VA_ARGS__)
|
||||||
|
#define SPAN_P_VAR(type, var, first, ...) SPAN_P(type) var(first, ##__VA_ARGS__)
|
||||||
|
#define SPAN_S_VAR(type, var, first, ...) SPAN_S(type) var(first, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
// create a value
|
||||||
|
#define SPAN_0_MAKE(type, first, ...) (SPAN_0(type)(first, ##__VA_ARGS__))
|
||||||
|
#define SPAN_P_MAKE(type, first, ...) (SPAN_P(type)(first, ##__VA_ARGS__))
|
||||||
|
#define SPAN_S_MAKE(type, first, ...) (SPAN_S(type)(first, ##__VA_ARGS__))
|
||||||
|
|
||||||
|
#elif WITH_SPAN >= 1
|
||||||
|
|
||||||
|
// unchecked - just a no-op pointer wrapper, no extra functionality
|
||||||
|
|
||||||
|
#define SPAN_0(type) Ptr<type>
|
||||||
|
#define SPAN_P(type) Ptr<type>
|
||||||
|
#define SPAN_S(type) Ptr<type>
|
||||||
|
|
||||||
|
// define a new variable
|
||||||
|
#define SPAN_0_VAR(type, var, first, ...) SPAN_0(type) var(first)
|
||||||
|
#define SPAN_P_VAR(type, var, first, ...) SPAN_P(type) var(first)
|
||||||
|
#define SPAN_S_VAR(type, var, first, ...) SPAN_S(type) var(first)
|
||||||
|
|
||||||
|
// create a value
|
||||||
|
#define SPAN_0_MAKE(type, first, ...) (SPAN_0(type)(first))
|
||||||
|
#define SPAN_P_MAKE(type, first, ...) (SPAN_P(type)(first))
|
||||||
|
#define SPAN_S_MAKE(type, first, ...) (SPAN_S(type)(first))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// unchecked raw pointers
|
||||||
|
|
||||||
|
// helper for implicit pointer conversions and MemBuffer overloads
|
||||||
|
template <class R, class T>
|
||||||
|
inline R *span_make__(R * /*dummy*/, T *first) {
|
||||||
|
return first; // IMPORTANT: no cast here to detect bad usage
|
||||||
|
}
|
||||||
|
template <class R>
|
||||||
|
inline R *span_make__(R * /*dummy*/, MemBuffer &first) {
|
||||||
|
return (R *) membuffer_get_void_ptr(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPAN_0(type) type *
|
||||||
|
#define SPAN_P(type) type *
|
||||||
|
#define SPAN_S(type) type *
|
||||||
|
|
||||||
|
// define a new variable
|
||||||
|
#define SPAN_0_VAR(type, var, first, ...) type *var = span_make__((type *) nullptr, first)
|
||||||
|
#define SPAN_P_VAR(type, var, first, ...) type *var = span_make__((type *) nullptr, first)
|
||||||
|
#define SPAN_S_VAR(type, var, first, ...) type *var = span_make__((type *) nullptr, first)
|
||||||
|
|
||||||
|
// create a value
|
||||||
|
#define SPAN_0_MAKE(type, first, ...) (span_make__((type *) nullptr, first))
|
||||||
|
#define SPAN_P_MAKE(type, first, ...) (span_make__((type *) nullptr, first))
|
||||||
|
#define SPAN_S_MAKE(type, first, ...) (span_make__((type *) nullptr, first))
|
||||||
|
|
||||||
|
#endif // WITH_SPAN
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
293
src/util/xspan_fwd.h
Normal file
293
src/util/xspan_fwd.h
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// manually forward a number of well-known functions using a
|
||||||
|
// checked "raw_bytes()" call
|
||||||
|
|
||||||
|
#define SPAN_FWD_TU(RType) \
|
||||||
|
template <class T, class U> \
|
||||||
|
inline SPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION(T, U, RType)
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// overloads for standard functions
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void *memchr(const C<T> &a, int c, size_t n) {
|
||||||
|
return memchr(a.raw_bytes(n), c, n);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline const void *memchr(const C<const T> &a, int c, size_t n) {
|
||||||
|
return memchr(a.raw_bytes(n), c, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline int memcmp(const C<T> &a, const void *b, size_t n) {
|
||||||
|
return memcmp(a.raw_bytes(n), b, n);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline int memcmp(const void *a, const C<T> &b, size_t n) {
|
||||||
|
return memcmp(a, b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
SPAN_FWD_TU(int) memcmp(const C<T> &a, const C<U> &b, size_t n) {
|
||||||
|
return memcmp(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#ifdef D
|
||||||
|
SPAN_FWD_TU(int) memcmp(const C<T> &a, const D<U> &b, size_t n) {
|
||||||
|
return memcmp(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef E
|
||||||
|
SPAN_FWD_TU(int) memcmp(const C<T> &a, const E<U> &b, size_t n) {
|
||||||
|
return memcmp(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void *memcpy(C<T> a, const void *b, size_t n) {
|
||||||
|
return memcpy(a.raw_bytes(n), b, n);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline void *memcpy(void *a, const C<T> &b, size_t n) {
|
||||||
|
return memcpy(a, b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
SPAN_FWD_TU(void *) memcpy(const C<T> &a, const C<U> &b, size_t n) {
|
||||||
|
return memcpy(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#ifdef D
|
||||||
|
SPAN_FWD_TU(void *) memcpy(const C<T> &a, const D<U> &b, size_t n) {
|
||||||
|
return memcpy(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef E
|
||||||
|
SPAN_FWD_TU(void *) memcpy(const C<T> &a, const E<U> &b, size_t n) {
|
||||||
|
return memcpy(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void *memmove(C<T> a, const void *b, size_t n) {
|
||||||
|
return memmove(a.raw_bytes(n), b, n);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline void *memmove(void *a, const C<T> &b, size_t n) {
|
||||||
|
return memmove(a, b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
SPAN_FWD_TU(void *) memmove(const C<T> &a, const C<U> &b, size_t n) {
|
||||||
|
return memmove(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#ifdef D
|
||||||
|
SPAN_FWD_TU(void *) memmove(const C<T> &a, const D<U> &b, size_t n) {
|
||||||
|
return memmove(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef E
|
||||||
|
SPAN_FWD_TU(void *) memmove(const C<T> &a, const E<U> &b, size_t n) {
|
||||||
|
return memmove(a.raw_bytes(n), b.raw_bytes(n), n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// overloads for UPX extras
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline int ptr_diff_bytes(const C<T> &a, const void *b) {
|
||||||
|
return ptr_diff_bytes(a.raw_bytes(0), b);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline int ptr_diff_bytes(const void *a, const C<T> &b) {
|
||||||
|
return ptr_diff_bytes(a, b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
SPAN_FWD_TU(int) ptr_diff_bytes(const C<T> &a, const C<U> &b) {
|
||||||
|
return ptr_diff_bytes(a.raw_bytes(0), b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
#ifdef D
|
||||||
|
SPAN_FWD_TU(int) ptr_diff_bytes(const C<T> &a, const D<U> &b) {
|
||||||
|
return ptr_diff_bytes(a.raw_bytes(0), b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef E
|
||||||
|
SPAN_FWD_TU(int) ptr_diff_bytes(const C<T> &a, const E<U> &b) {
|
||||||
|
return ptr_diff_bytes(a.raw_bytes(0), b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline unsigned ptr_udiff_bytes(const C<T> &a, const void *b) {
|
||||||
|
return ptr_udiff_bytes(a.raw_bytes(0), b);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline unsigned ptr_udiff_bytes(const void *a, const C<T> &b) {
|
||||||
|
return ptr_udiff_bytes(a, b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
SPAN_FWD_TU(unsigned) ptr_udiff_bytes(const C<T> &a, const C<U> &b) {
|
||||||
|
return ptr_udiff_bytes(a.raw_bytes(0), b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
#ifdef D
|
||||||
|
SPAN_FWD_TU(unsigned) ptr_udiff_bytes(const C<T> &a, const D<U> &b) {
|
||||||
|
return ptr_udiff_bytes(a.raw_bytes(0), b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef E
|
||||||
|
SPAN_FWD_TU(unsigned) ptr_udiff_bytes(const C<T> &a, const E<U> &b) {
|
||||||
|
return ptr_udiff_bytes(a.raw_bytes(0), b.raw_bytes(0));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
unsigned get_ne16(const C<T> &a) {
|
||||||
|
return get_ne16(a.raw_bytes(2));
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
unsigned get_ne32(const C<T> &a) {
|
||||||
|
return get_ne32(a.raw_bytes(4));
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
upx_uint64_t get_ne64(const C<T> &a) {
|
||||||
|
return get_ne64(a.raw_bytes(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
unsigned get_be16(const C<T> &a) {
|
||||||
|
return get_be16(a.raw_bytes(2));
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
unsigned get_be32(const C<T> &a) {
|
||||||
|
return get_be32(a.raw_bytes(4));
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
upx_uint64_t get_be64(const C<T> &a) {
|
||||||
|
return get_be64(a.raw_bytes(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
unsigned get_le16(const C<T> &a) {
|
||||||
|
return get_le16(a.raw_bytes(2));
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
unsigned get_le24(const C<T> &a) {
|
||||||
|
return get_le24(a.raw_bytes(3));
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
unsigned get_le32(const C<T> &a) {
|
||||||
|
return get_le32(a.raw_bytes(4));
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
upx_uint64_t get_le64(const C<T> &a) {
|
||||||
|
return get_le64(a.raw_bytes(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void set_ne16(const C<T> &a, unsigned v) {
|
||||||
|
return set_ne16(a.raw_bytes(2), v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void set_ne32(const C<T> &a, unsigned v) {
|
||||||
|
return set_ne32(a.raw_bytes(4), v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void set_ne64(const C<T> &a, upx_uint64_t v) {
|
||||||
|
return set_ne64(a.raw_bytes(8), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void set_be16(const C<T> &a, unsigned v) {
|
||||||
|
return set_be16(a.raw_bytes(2), v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void set_be32(const C<T> &a, unsigned v) {
|
||||||
|
return set_be32(a.raw_bytes(4), v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void set_be64(const C<T> &a, upx_uint64_t v) {
|
||||||
|
return set_be64(a.raw_bytes(8), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void set_le16(const C<T> &a, unsigned v) {
|
||||||
|
return set_le16(a.raw_bytes(2), v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void set_le24(const C<T> &a, unsigned v) {
|
||||||
|
return set_le24(a.raw_bytes(3), v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void set_le32(const C<T> &a, unsigned v) {
|
||||||
|
return set_le32(a.raw_bytes(4), v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void set_le64(const C<T> &a, upx_uint64_t v) {
|
||||||
|
return set_le64(a.raw_bytes(8), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator+(const C<T> &a, const BE16 &v) {
|
||||||
|
return a + unsigned(v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator+(const C<T> &a, const BE32 &v) {
|
||||||
|
return a + unsigned(v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator+(const C<T> &a, const LE16 &v) {
|
||||||
|
return a + unsigned(v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator+(const C<T> &a, const LE32 &v) {
|
||||||
|
return a + unsigned(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator-(const C<T> &a, const BE16 &v) {
|
||||||
|
return a - unsigned(v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator-(const C<T> &a, const BE32 &v) {
|
||||||
|
return a - unsigned(v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator-(const C<T> &a, const LE16 &v) {
|
||||||
|
return a - unsigned(v);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline C<T> operator-(const C<T> &a, const LE32 &v) {
|
||||||
|
return a - unsigned(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
typename std::enable_if<sizeof(T) == 1, upx_rsize_t>::type upx_safe_strlen(const C<T> &a) {
|
||||||
|
// not fully checked, but can require at least 1 byte
|
||||||
|
return upx_safe_strlen(a.raw_bytes(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UPX_VERSION_HEX
|
||||||
|
|
||||||
|
#undef SPAN_FWD_TU
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
240
src/util/xspan_impl.h
Normal file
240
src/util/xspan_impl.h
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if WITH_SPAN
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#define SPAN_NAMESPACE_NAME XSpan
|
||||||
|
#define SPAN_NAMESPACE_BEGIN namespace SPAN_NAMESPACE_NAME {
|
||||||
|
#define SPAN_NAMESPACE_END }
|
||||||
|
#define SPAN_NS(x) SPAN_NAMESPACE_NAME ::x
|
||||||
|
#else
|
||||||
|
#define SPAN_NAMESPACE_BEGIN /*empty*/
|
||||||
|
#define SPAN_NAMESPACE_END /*empty*/
|
||||||
|
#define SPAN_NS(x) ::x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
__acc_noinline void span_fail_nullptr();
|
||||||
|
__acc_noinline void span_fail_not_same_base();
|
||||||
|
__acc_noinline void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes);
|
||||||
|
|
||||||
|
// help constructor to distinguish between number of elements and bytes
|
||||||
|
struct SpanCount {
|
||||||
|
explicit SpanCount(size_t n) : count(n) {}
|
||||||
|
size_t count; // public
|
||||||
|
};
|
||||||
|
struct SpanSizeInBytes {
|
||||||
|
explicit SpanSizeInBytes(size_t bytes) : size_in_bytes(bytes) {}
|
||||||
|
size_t size_in_bytes; // public
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct TypeForSizeOf {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct TypeForSizeOf<void> {
|
||||||
|
typedef char type;
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct TypeForSizeOf<const void> {
|
||||||
|
typedef const char type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct ValueForSizeOf {
|
||||||
|
static const size_t value = sizeof(typename TypeForSizeOf<T>::type);
|
||||||
|
};
|
||||||
|
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf<char>::value == 1)
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf<const char>::value == 1)
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf<void>::value == 1)
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf<const void>::value == 1)
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf<int>::value == 4)
|
||||||
|
|
||||||
|
#ifndef span_mem_size_impl
|
||||||
|
template <class T>
|
||||||
|
inline size_t span_mem_size_impl(size_t n) {
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
// check for overflow and sane limits
|
||||||
|
return mem_size(sizeof(T), n);
|
||||||
|
#else
|
||||||
|
return sizeof(T) * n;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline size_t span_mem_size(size_t n) {
|
||||||
|
return span_mem_size_impl<typename TypeForSizeOf<T>::type>(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void span_mem_size_assert_ptrdiff(ptrdiff_t n) {
|
||||||
|
if (n >= 0)
|
||||||
|
(void) span_mem_size<T>((size_t) n);
|
||||||
|
else
|
||||||
|
(void) span_mem_size<T>((size_t) -n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
template <class From, class To>
|
||||||
|
struct Span_is_convertible : public std::is_convertible<From *, To *> {};
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <class T, class U>
|
||||||
|
struct Span_void_to_T {
|
||||||
|
typedef U type;
|
||||||
|
};
|
||||||
|
template <class T>
|
||||||
|
struct Span_void_to_T<T, void> {
|
||||||
|
typedef typename std::remove_const<T>::type type;
|
||||||
|
};
|
||||||
|
template <class T>
|
||||||
|
struct Span_void_to_T<T, const void> {
|
||||||
|
// typedef typename std::add_const<T>::type type;
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class From, class To>
|
||||||
|
struct Span_ptr_is_convertible : public std::false_type {};
|
||||||
|
template <class T>
|
||||||
|
struct Span_ptr_is_convertible<T, T> : public std::true_type {};
|
||||||
|
template <class T>
|
||||||
|
struct Span_ptr_is_convertible<T, const T> : public std::true_type {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <class From, class To>
|
||||||
|
struct Span_is_convertible
|
||||||
|
: public detail::Span_ptr_is_convertible<From,
|
||||||
|
typename detail::Span_void_to_T<From, To>::type> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// char => char
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<char, char>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<char, const char>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<const char, const char>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<const char, char>::value));
|
||||||
|
|
||||||
|
// void => void
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<void, void>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<void, const void>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<const void, const void>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<const void, void>::value));
|
||||||
|
|
||||||
|
// char => void
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<char, void>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<char, const void>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible<const char, const void>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<const char, void>::value));
|
||||||
|
|
||||||
|
// void => char
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<void, char>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<void, const char>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<const void, const char>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<const void, char>::value));
|
||||||
|
|
||||||
|
// char => int
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(!(Span_is_convertible<char, int>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(!(Span_is_convertible<char, const int>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(!(Span_is_convertible<const char, const int>::value));
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible<const char, int>::value));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// PtrOrSpanOrNull
|
||||||
|
// PtrOrSpan
|
||||||
|
// Span
|
||||||
|
// Ptr
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct PtrOrSpanOrNull;
|
||||||
|
template <class T>
|
||||||
|
struct PtrOrSpan;
|
||||||
|
template <class T>
|
||||||
|
struct Span;
|
||||||
|
template <class T>
|
||||||
|
struct Ptr;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const PtrOrSpanOrNull<T> &a, size_t size_in_bytes);
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const PtrOrSpan<T> &a, size_t size_in_bytes);
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const Span<T> &a, size_t size_in_bytes);
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const Ptr<T> &a, size_t size_in_bytes);
|
||||||
|
|
||||||
|
class SpanInternalDummyArg; // not implemented
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifndef SPAN_DELETED_FUNCTION
|
||||||
|
#define SPAN_DELETED_FUNCTION = delete
|
||||||
|
#endif
|
||||||
|
#define SPAN_REQUIRES_CONVERTIBLE_UT(T, U, RType) \
|
||||||
|
typename std::enable_if<SPAN_NS(Span_is_convertible) < U, T>::value, RType > ::type
|
||||||
|
#define SPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION(T, U, RType) \
|
||||||
|
typename std::enable_if<SPAN_NS(Span_is_convertible) < U, T>::value || \
|
||||||
|
SPAN_NS(Span_is_convertible)<T, U>::value, \
|
||||||
|
RType > ::type
|
||||||
|
// note: these use "T" and "U"
|
||||||
|
#define SPAN_REQUIRES_CONVERTIBLE_R(RType) SPAN_REQUIRES_CONVERTIBLE_UT(T, U, RType)
|
||||||
|
#define SPAN_REQUIRES_CONVERTIBLE_A \
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(SPAN_NS(SpanInternalDummyArg) *) = nullptr
|
||||||
|
#define SPAN_REQUIRES_CONVERTIBLE_T SPAN_REQUIRES_CONVERTIBLE_R(SPAN_NS(SpanInternalDummyArg) *)
|
||||||
|
// note: these use "T" and "U"
|
||||||
|
#define SPAN_REQUIRES_SIZE_1_R(RType) \
|
||||||
|
typename std::enable_if<SPAN_NS(Span_is_convertible) < U, T>::value &&SPAN_NS( \
|
||||||
|
ValueForSizeOf)<T>::value == 1 && \
|
||||||
|
SPAN_NS(ValueForSizeOf)<U>::value == 1, \
|
||||||
|
RType > ::type
|
||||||
|
#define SPAN_REQUIRES_SIZE_1_A SPAN_REQUIRES_SIZE_1_R(SPAN_NS(SpanInternalDummyArg) *) = nullptr
|
||||||
|
|
||||||
|
#include "xspan_impl_ptr_or_null.h"
|
||||||
|
#include "xspan_impl_ptr_or_span.h"
|
||||||
|
#include "xspan_impl_span.h"
|
||||||
|
#include "xspan_impl_ptr.h"
|
||||||
|
#undef SPAN_REQUIRES_CONVERTIBLE_UT
|
||||||
|
#undef SPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION
|
||||||
|
#undef SPAN_REQUIRES_CONVERTIBLE_A
|
||||||
|
#undef SPAN_REQUIRES_CONVERTIBLE_R
|
||||||
|
#undef SPAN_REQUIRES_CONVERTIBLE_T
|
||||||
|
#undef SPAN_REQUIRES_SIZE_1_A
|
||||||
|
#undef SPAN_REQUIRES_SIZE_1_R
|
||||||
|
|
||||||
|
#endif // WITH_SPAN
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
417
src/util/xspan_impl_common.h
Normal file
417
src/util/xspan_impl_common.h
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef T element_type;
|
||||||
|
typedef typename std::add_lvalue_reference<T>::type reference;
|
||||||
|
// typedef typename std::add_pointer<T>::type pointer;
|
||||||
|
typedef T *pointer;
|
||||||
|
typedef size_t size_type;
|
||||||
|
|
||||||
|
// befriend all
|
||||||
|
template <class>
|
||||||
|
friend struct PtrOrSpan;
|
||||||
|
template <class>
|
||||||
|
friend struct PtrOrSpanOrNull;
|
||||||
|
template <class>
|
||||||
|
friend struct Span;
|
||||||
|
|
||||||
|
#if SPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION
|
||||||
|
operator pointer() const { return ptr; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
pointer ptr; // current view into (base, base+size_in_bytes) iff base != nullptr
|
||||||
|
pointer base;
|
||||||
|
size_type size_in_bytes;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// disable taking the address => force passing by reference
|
||||||
|
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
||||||
|
Self *operator&() const SPAN_DELETED_FUNCTION;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static __acc_forceinline pointer makeNotNull(pointer p) {
|
||||||
|
if __acc_very_unlikely (p == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
// enforce config invariants at constructor time - static functions
|
||||||
|
static __acc_forceinline pointer makePtr(pointer p) {
|
||||||
|
if __acc_cte (configRequirePtr && p == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
static __acc_forceinline pointer makeBase(pointer b) {
|
||||||
|
if __acc_cte (configRequireBase && b == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
// inverse logic for ensuring valid pointers from existing objets
|
||||||
|
__acc_forceinline pointer ensurePtr() const {
|
||||||
|
if __acc_cte (!configRequirePtr && ptr == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
__acc_forceinline pointer ensureBase() const {
|
||||||
|
if __acc_cte (!configRequireBase && base == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
// debug - extra internal sanity checks
|
||||||
|
#if DEBUG || 1
|
||||||
|
__acc_noinline void assertInvariants() const {
|
||||||
|
if __acc_cte (configRequirePtr)
|
||||||
|
assert(ptr != nullptr);
|
||||||
|
if __acc_cte (configRequireBase)
|
||||||
|
assert(base != nullptr);
|
||||||
|
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||||
|
span_check_range(ptr, base, size_in_bytes);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
__acc_forceinline void assertInvariants() const {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline ~CSelf() {}
|
||||||
|
// constructors from pointers
|
||||||
|
CSelf(pointer first, SpanCount count)
|
||||||
|
: ptr(makePtr(first)), base(makeBase(first)), size_in_bytes(span_mem_size<T>(count.count)) {
|
||||||
|
assertInvariants();
|
||||||
|
}
|
||||||
|
CSelf(pointer first, SpanSizeInBytes bytes)
|
||||||
|
: ptr(makePtr(first)), base(makeBase(first)),
|
||||||
|
size_in_bytes(span_mem_size<char>(bytes.size_in_bytes)) {
|
||||||
|
assertInvariants();
|
||||||
|
}
|
||||||
|
// enable this constructor only if the underlying type is char or void
|
||||||
|
template <class U>
|
||||||
|
CSelf(U *first, size_type count, SPAN_REQUIRES_SIZE_1_A)
|
||||||
|
: ptr(makePtr(first)), base(makeBase(first)), size_in_bytes(span_mem_size<T>(count)) {
|
||||||
|
assertInvariants();
|
||||||
|
}
|
||||||
|
CSelf(pointer first, SpanCount count, pointer base_)
|
||||||
|
: ptr(makePtr(first)), base(makeBase(base_)), size_in_bytes(span_mem_size<T>(count.count)) {
|
||||||
|
// check invariants
|
||||||
|
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||||
|
span_check_range(ptr, base, size_in_bytes);
|
||||||
|
// double sanity check
|
||||||
|
assertInvariants();
|
||||||
|
}
|
||||||
|
CSelf(pointer first, SpanSizeInBytes bytes, pointer base_)
|
||||||
|
: ptr(makePtr(first)), base(makeBase(base_)),
|
||||||
|
size_in_bytes(span_mem_size<char>(bytes.size_in_bytes)) {
|
||||||
|
// check invariants
|
||||||
|
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||||
|
span_check_range(ptr, base, size_in_bytes);
|
||||||
|
// double sanity check
|
||||||
|
assertInvariants();
|
||||||
|
}
|
||||||
|
// enable this constructor only if the underlying type is char or void
|
||||||
|
template <class U>
|
||||||
|
CSelf(pointer first, size_type count, U *base_, SPAN_REQUIRES_SIZE_1_A)
|
||||||
|
: ptr(makePtr(first)), base(makeBase(base_)), size_in_bytes(span_mem_size<T>(count)) {
|
||||||
|
// check invariants
|
||||||
|
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||||
|
span_check_range(ptr, base, size_in_bytes);
|
||||||
|
// double sanity check
|
||||||
|
assertInvariants();
|
||||||
|
}
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
// constructors from MemBuffer
|
||||||
|
CSelf(MemBuffer &mb)
|
||||||
|
: CSelf(makeNotNull((pointer) membuffer_get_void_ptr(mb)),
|
||||||
|
SpanSizeInBytes(membuffer_get_size(mb))) {}
|
||||||
|
CSelf(pointer first, MemBuffer &mb)
|
||||||
|
: CSelf(first, SpanSizeInBytes(membuffer_get_size(mb)),
|
||||||
|
makeNotNull((pointer) membuffer_get_void_ptr(mb))) {}
|
||||||
|
CSelf(std::nullptr_t, MemBuffer &) SPAN_DELETED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
// disable constructors from nullptr to catch compile-time misuse
|
||||||
|
private:
|
||||||
|
CSelf(std::nullptr_t, SpanCount) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, SpanCount, std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(const void *, SpanCount, std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, SpanSizeInBytes) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, SpanSizeInBytes, std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(const void *, SpanSizeInBytes, std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, size_type) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, size_type, std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(const void *, size_type, std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
|
||||||
|
// unchecked constructor
|
||||||
|
private:
|
||||||
|
enum ModeUnchecked { Unchecked };
|
||||||
|
CSelf(ModeUnchecked, pointer p, size_type bytes, pointer b)
|
||||||
|
: ptr(p), base(b), size_in_bytes(bytes) {
|
||||||
|
assertInvariants();
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
// unchecked assignment
|
||||||
|
Self &assign(ModeUnchecked, pointer p, size_type bytes, pointer b) {
|
||||||
|
ptr = p;
|
||||||
|
base = b;
|
||||||
|
size_in_bytes = bytes;
|
||||||
|
assertInvariants();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self &assign(ModeUnchecked, const Self &other) {
|
||||||
|
ptr = other.ptr;
|
||||||
|
base = other.base;
|
||||||
|
size_in_bytes = other.size_in_bytes;
|
||||||
|
assertInvariants();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
// assignment - here we can rely on invariants enforced at construction time by makePtr/makeBase
|
||||||
|
// NOTE: *this remains unmodified in case of failure
|
||||||
|
Self &assign(pointer other) {
|
||||||
|
assertInvariants();
|
||||||
|
other = makePtr(other);
|
||||||
|
if __acc_cte ((configRequirePtr || other != nullptr) && (configRequireBase || base != nullptr))
|
||||||
|
span_check_range(other, base, size_in_bytes);
|
||||||
|
// ok
|
||||||
|
ptr = other;
|
||||||
|
assertInvariants();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self &assign(const Self &other) {
|
||||||
|
assertInvariants();
|
||||||
|
other.assertInvariants();
|
||||||
|
if __acc_cte (!configRequireBase && base == nullptr) {
|
||||||
|
// magic 1: if base is unset, automatically set base/size_in_bytes from other
|
||||||
|
if __acc_cte ((configRequirePtr || other.ptr != nullptr) &&
|
||||||
|
(configRequireBase || other.base != nullptr))
|
||||||
|
span_check_range(other.ptr, other.base, other.size_in_bytes);
|
||||||
|
// ok
|
||||||
|
ptr = other.ptr;
|
||||||
|
base = other.base;
|
||||||
|
size_in_bytes = other.size_in_bytes;
|
||||||
|
} else {
|
||||||
|
// magic 2: assert same base (but ignore size_in_bytes !)
|
||||||
|
if __acc_cte (configRequireBase || other.base != nullptr)
|
||||||
|
if __acc_very_unlikely (base != other.base)
|
||||||
|
span_fail_not_same_base();
|
||||||
|
if __acc_cte ((configRequirePtr || other.ptr != nullptr) &&
|
||||||
|
(configRequireBase || base != nullptr))
|
||||||
|
span_check_range(other.ptr, base, size_in_bytes);
|
||||||
|
// ok
|
||||||
|
ptr = other.ptr;
|
||||||
|
}
|
||||||
|
assertInvariants();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Self &operator=(pointer other) { return assign(other); }
|
||||||
|
|
||||||
|
Self &operator=(const Self &other) { return assign(other); }
|
||||||
|
|
||||||
|
// FIXME: this is not called??
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const CSelf<U> &other) {
|
||||||
|
// assert(0);
|
||||||
|
return assign(Self(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
Self &operator=(MemBuffer &mb) { return assign(Self(mb)); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Self subspan(ptrdiff_t offset, ptrdiff_t count) {
|
||||||
|
pointer begin = check_add(ptr, offset);
|
||||||
|
pointer end = check_add(begin, count);
|
||||||
|
if (begin <= end)
|
||||||
|
return Self(Unchecked, begin, (end - begin) * sizeof(T), begin);
|
||||||
|
else
|
||||||
|
return Self(Unchecked, end, (begin - end) * sizeof(T), end);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(pointer other) const { return ptr == other; }
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator==(U *other) const {
|
||||||
|
return ptr == other;
|
||||||
|
}
|
||||||
|
bool operator!=(pointer other) const { return ptr != other; }
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator!=(U *other) const {
|
||||||
|
return ptr != other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator==(const PtrOrSpan<U> &other) const {
|
||||||
|
return ptr == other.ptr;
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator==(const PtrOrSpanOrNull<U> &other) const {
|
||||||
|
return ptr == other.ptr;
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator==(const Span<U> &other) const {
|
||||||
|
return ptr == other.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator!=(const PtrOrSpan<U> &other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator!=(const PtrOrSpanOrNull<U> &other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator!=(const Span<U> &other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for notNull here
|
||||||
|
bool operator<(std::nullptr_t) const SPAN_DELETED_FUNCTION;
|
||||||
|
bool operator<(pointer other) const { return ensurePtr() < makeNotNull(other); }
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator<(const PtrOrSpan<U> &other) const {
|
||||||
|
return ensurePtr() < other.ensurePtr();
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator<(const PtrOrSpanOrNull<U> &other) const {
|
||||||
|
return ensurePtr() < other.ensurePtr();
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator<(const Span<U> &other) const {
|
||||||
|
return ensurePtr() < other.ensurePtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
// dereference
|
||||||
|
reference operator*() const { return *check_deref(ptr); }
|
||||||
|
|
||||||
|
// array access
|
||||||
|
reference operator[](ptrdiff_t i) const { return *check_deref(ptr, i); }
|
||||||
|
|
||||||
|
// arrow operator
|
||||||
|
pointer operator->() const { return check_deref(ptr); }
|
||||||
|
|
||||||
|
Self &operator++() {
|
||||||
|
ptr = check_add(ptr, 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self operator++(int) {
|
||||||
|
Self tmp = *this;
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
Self &operator--() {
|
||||||
|
ptr = check_add(ptr, -1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self operator--(int) {
|
||||||
|
Self tmp = *this;
|
||||||
|
--*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Self &operator+=(ptrdiff_t n) {
|
||||||
|
ptr = check_add(ptr, n);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self &operator-=(ptrdiff_t n) {
|
||||||
|
ptr = check_add(ptr, -n);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Self operator+(ptrdiff_t n) const {
|
||||||
|
pointer first = check_add(ptr, n);
|
||||||
|
return Self(Unchecked, first, size_in_bytes, base);
|
||||||
|
}
|
||||||
|
Self operator-(ptrdiff_t n) const {
|
||||||
|
pointer first = check_add(ptr, -n);
|
||||||
|
return Self(Unchecked, first, size_in_bytes, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
pointer check_deref(pointer p) const {
|
||||||
|
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
if __acc_cte (configRequireBase || base != nullptr)
|
||||||
|
span_check_range(p, base, size_in_bytes - sizeof(T));
|
||||||
|
assertInvariants();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
pointer check_deref(pointer p, ptrdiff_t n) const {
|
||||||
|
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
span_mem_size_assert_ptrdiff<T>(n);
|
||||||
|
p += n;
|
||||||
|
if __acc_cte (configRequireBase || base != nullptr)
|
||||||
|
span_check_range(p, base, size_in_bytes - sizeof(T));
|
||||||
|
assertInvariants();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
pointer check_add(pointer p, ptrdiff_t n) const {
|
||||||
|
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
span_mem_size_assert_ptrdiff<T>(n);
|
||||||
|
p += n;
|
||||||
|
if __acc_cte (configRequireBase || base != nullptr)
|
||||||
|
span_check_range(p, base, size_in_bytes);
|
||||||
|
assertInvariants();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // raw access
|
||||||
|
pointer raw_ptr() const { return ptr; }
|
||||||
|
pointer raw_base() const { return base; }
|
||||||
|
size_type raw_size_in_bytes() const { return size_in_bytes; }
|
||||||
|
|
||||||
|
pointer raw_bytes(size_t bytes) const {
|
||||||
|
assertInvariants();
|
||||||
|
if (bytes > 0) {
|
||||||
|
if __acc_cte (!configRequirePtr && ptr == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
if __acc_cte (configRequireBase || base != nullptr) {
|
||||||
|
span_check_range(ptr, base, size_in_bytes - bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
209
src/util/xspan_impl_ptr.h
Normal file
209
src/util/xspan_impl_ptr.h
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// Ptr
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct Ptr {
|
||||||
|
private:
|
||||||
|
#define CSelf Ptr
|
||||||
|
typedef CSelf<T> Self;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// befriend all
|
||||||
|
template <class>
|
||||||
|
friend struct CSelf;
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
typedef typename std::add_lvalue_reference<T>::type reference;
|
||||||
|
// typedef T *pointer;
|
||||||
|
typedef typename std::add_pointer<T>::type pointer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pointer ptr;
|
||||||
|
|
||||||
|
// enforce config invariants at constructor time - static functions
|
||||||
|
static __acc_forceinline pointer makePtr(pointer p) { return p; }
|
||||||
|
// inverse logic for ensuring valid pointers from existing objets
|
||||||
|
__acc_forceinline pointer ensurePtr() const { return ptr; }
|
||||||
|
// debug
|
||||||
|
__acc_forceinline void assertInvariants() const {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
#if SPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1
|
||||||
|
operator pointer() const { return ptr; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline ~CSelf() {}
|
||||||
|
inline CSelf() {}
|
||||||
|
|
||||||
|
// constructors from pointers
|
||||||
|
CSelf(pointer p) : ptr(makePtr(p)) {}
|
||||||
|
template <class U>
|
||||||
|
CSelf(U *p, SPAN_REQUIRES_CONVERTIBLE_A) : ptr(makePtr(p)) {}
|
||||||
|
|
||||||
|
// constructors
|
||||||
|
CSelf(const Self &other) : ptr(other.ptr) {}
|
||||||
|
template <class U>
|
||||||
|
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A) : ptr(other.ptr) {}
|
||||||
|
|
||||||
|
Self &assign(const Self &other) {
|
||||||
|
assertInvariants();
|
||||||
|
other.assertInvariants();
|
||||||
|
ptr = other.ptr;
|
||||||
|
assertInvariants();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assignment
|
||||||
|
Self &operator=(const Self &other) { return assign(other); }
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(U *other) {
|
||||||
|
assert(0);
|
||||||
|
return assign(Self(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: this is not called !!
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const CSelf<U> &other) {
|
||||||
|
assert(0);
|
||||||
|
return assign(Self(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
// comparision
|
||||||
|
|
||||||
|
bool operator==(pointer other) const { return ptr == other; }
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator==(U *other) const {
|
||||||
|
return ptr == other;
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||||
|
operator==(const Ptr<U> &other) const {
|
||||||
|
return ptr == other.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dereference
|
||||||
|
reference operator*() const { return *check_deref(ptr); }
|
||||||
|
|
||||||
|
// array access
|
||||||
|
reference operator[](ptrdiff_t i) const { return *check_deref(ptr, i); }
|
||||||
|
|
||||||
|
// arrow operator
|
||||||
|
pointer operator->() const { return check_deref(ptr); }
|
||||||
|
|
||||||
|
Self &operator++() {
|
||||||
|
ptr = check_add(ptr, 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self operator++(int) {
|
||||||
|
Self tmp = *this;
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
Self &operator--() {
|
||||||
|
ptr = check_add(ptr, -1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self operator--(int) {
|
||||||
|
Self tmp = *this;
|
||||||
|
--*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Self &operator+=(ptrdiff_t n) {
|
||||||
|
ptr = check_add(ptr, n);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Self &operator-=(ptrdiff_t n) {
|
||||||
|
ptr = check_add(ptr, -n);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Self operator+(ptrdiff_t n) const {
|
||||||
|
pointer p = check_add(ptr, n);
|
||||||
|
return Self(p);
|
||||||
|
}
|
||||||
|
Self operator-(ptrdiff_t n) const {
|
||||||
|
pointer p = check_add(ptr, -n);
|
||||||
|
return Self(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CSelf(MemBuffer &mb) : ptr((pointer) membuffer_get_void_ptr(mb)) {}
|
||||||
|
Self &operator=(MemBuffer &mb) { return assign(Self(mb)); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
__acc_forceinline pointer check_deref(pointer p) const { return p; }
|
||||||
|
__acc_forceinline pointer check_deref(pointer p, ptrdiff_t n) const { return p + n; }
|
||||||
|
__acc_forceinline pointer check_add(pointer p, ptrdiff_t n) const { return p + n; }
|
||||||
|
|
||||||
|
public: // raw access
|
||||||
|
pointer raw_ptr() const { return ptr; }
|
||||||
|
|
||||||
|
pointer raw_bytes(size_t bytes) const {
|
||||||
|
assertInvariants();
|
||||||
|
if (bytes > 0) {
|
||||||
|
if __acc_cte (ptr == nullptr)
|
||||||
|
span_fail_nullptr();
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CSelf
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const Ptr<T> &a, size_t size_in_bytes) {
|
||||||
|
return a.raw_bytes(size_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_END
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
#define C SPAN_NS(Ptr)
|
||||||
|
#include "xspan_fwd.h"
|
||||||
|
#undef C
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
108
src/util/xspan_impl_ptr_or_null.h
Normal file
108
src/util/xspan_impl_ptr_or_null.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// PtrOrSpanOrNull
|
||||||
|
//
|
||||||
|
// invariants:
|
||||||
|
// ptr can be null
|
||||||
|
// if ptr != null && base != null then ptr is valid in base
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct PtrOrSpanOrNull {
|
||||||
|
private:
|
||||||
|
#define CSelf PtrOrSpanOrNull
|
||||||
|
typedef CSelf<T> Self;
|
||||||
|
// core config
|
||||||
|
enum { configRequirePtr = false };
|
||||||
|
enum { configRequireBase = false };
|
||||||
|
|
||||||
|
#include "xspan_impl_common.h"
|
||||||
|
public:
|
||||||
|
// constructors from pointers
|
||||||
|
CSelf(pointer first) : ptr(first), base(nullptr), size_in_bytes(0) {}
|
||||||
|
|
||||||
|
// constructors
|
||||||
|
CSelf(const Self &other)
|
||||||
|
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
template <class U>
|
||||||
|
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
|
||||||
|
// constructors from Span friends
|
||||||
|
template <class U>
|
||||||
|
CSelf(const PtrOrSpan<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
template <class U>
|
||||||
|
CSelf(const Span<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
|
||||||
|
// assignment from Span friends
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const PtrOrSpan<U> &other) {
|
||||||
|
return assign(Self(other));
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const Span<U> &other) {
|
||||||
|
return assign(Self(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
// nullptr
|
||||||
|
CSelf(std::nullptr_t) : ptr(nullptr), base(nullptr), size_in_bytes(0) {}
|
||||||
|
#undef CSelf
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const PtrOrSpanOrNull<T> &a, size_t size_in_bytes) {
|
||||||
|
return a.raw_bytes(size_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_END
|
||||||
|
|
||||||
|
#if !SPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1
|
||||||
|
|
||||||
|
#define C SPAN_NS(PtrOrSpanOrNull)
|
||||||
|
#define D SPAN_NS(PtrOrSpan)
|
||||||
|
#define E SPAN_NS(Span)
|
||||||
|
#include "xspan_fwd.h"
|
||||||
|
#undef C
|
||||||
|
#undef D
|
||||||
|
#undef E
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
133
src/util/xspan_impl_ptr_or_span.h
Normal file
133
src/util/xspan_impl_ptr_or_span.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// PtrOrSpan
|
||||||
|
//
|
||||||
|
// invariants:
|
||||||
|
// ptr != null
|
||||||
|
// if base != null then ptr is valid in base
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct PtrOrSpan {
|
||||||
|
private:
|
||||||
|
#define CSelf PtrOrSpan
|
||||||
|
typedef CSelf<T> Self;
|
||||||
|
// core config
|
||||||
|
enum { configRequirePtr = true };
|
||||||
|
enum { configRequireBase = false };
|
||||||
|
|
||||||
|
#include "xspan_impl_common.h"
|
||||||
|
public:
|
||||||
|
// constructors from pointers
|
||||||
|
CSelf(pointer first) : ptr(makePtr(first)), base(nullptr), size_in_bytes(0) {}
|
||||||
|
|
||||||
|
// constructors
|
||||||
|
CSelf(const Self &other)
|
||||||
|
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
template <class U>
|
||||||
|
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
|
||||||
|
// constructors from Span friends
|
||||||
|
template <class U>
|
||||||
|
CSelf(const Span<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
template <class U>
|
||||||
|
CSelf(const PtrOrSpanOrNull<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// assignment from Span friends
|
||||||
|
// TODO: use Unchecked to avoid double checks in both constructor and assignment
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const Span<U> &other) {
|
||||||
|
return assign(Self(other));
|
||||||
|
}
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const PtrOrSpanOrNull<U> &other) {
|
||||||
|
if (other.base == nullptr)
|
||||||
|
return assign(Self(other.ptr, size_in_bytes, base));
|
||||||
|
return assign(Self(other.ptr, other.size_in_bytes, other.base));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// nullptr
|
||||||
|
CSelf(std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, SpanSizeInBytes, const void *) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, SpanCount, const void *) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, size_type, const void *) SPAN_DELETED_FUNCTION;
|
||||||
|
Self &operator=(std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
#if 0
|
||||||
|
// don't enable, this prevents generic usage
|
||||||
|
bool operator==(std::nullptr_t) const SPAN_DELETED_FUNCTION;
|
||||||
|
bool operator!=(std::nullptr_t) const SPAN_DELETED_FUNCTION;
|
||||||
|
#else
|
||||||
|
bool operator==(std::nullptr_t) const {
|
||||||
|
assertInvariants();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool operator!=(std::nullptr_t) const {
|
||||||
|
assertInvariants();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#undef CSelf
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const PtrOrSpan<T> &a, size_t size_in_bytes) {
|
||||||
|
return a.raw_bytes(size_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_END
|
||||||
|
|
||||||
|
#if !SPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1
|
||||||
|
|
||||||
|
#define C SPAN_NS(PtrOrSpan)
|
||||||
|
#define D SPAN_NS(PtrOrSpanOrNull)
|
||||||
|
#define E SPAN_NS(Span)
|
||||||
|
#include "xspan_fwd.h"
|
||||||
|
#undef C
|
||||||
|
#undef D
|
||||||
|
#undef E
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
135
src/util/xspan_impl_span.h
Normal file
135
src/util/xspan_impl_span.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2022 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// Span
|
||||||
|
//
|
||||||
|
// invariants:
|
||||||
|
// ptr != null, base != null
|
||||||
|
// ptr is valid in base
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct Span {
|
||||||
|
private:
|
||||||
|
#define CSelf Span
|
||||||
|
typedef CSelf<T> Self;
|
||||||
|
// core config
|
||||||
|
enum { configRequirePtr = true };
|
||||||
|
enum { configRequireBase = true };
|
||||||
|
|
||||||
|
#include "xspan_impl_common.h"
|
||||||
|
public:
|
||||||
|
// constructors from pointers
|
||||||
|
CSelf(pointer first) SPAN_DELETED_FUNCTION;
|
||||||
|
|
||||||
|
// constructors
|
||||||
|
CSelf(const Self &other)
|
||||||
|
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
template <class U>
|
||||||
|
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
|
||||||
|
// constructors from Span friends
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
template <class U>
|
||||||
|
CSelf(const PtrOrSpanOrNull<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
template <class U>
|
||||||
|
CSelf(const PtrOrSpan<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
|
||||||
|
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// assignment from Span friends
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
// TODO: use Unchecked to avoid double checks in both constructor and assignment
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const PtrOrSpan<U> &other) {
|
||||||
|
if (other.base == nullptr)
|
||||||
|
return assign(Self(other.ptr, size_in_bytes, base));
|
||||||
|
return assign(Self(other.ptr, other.size_in_bytes, other.base));
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||||
|
operator=(const PtrOrSpanOrNull<U> &other) {
|
||||||
|
if (other.base == nullptr)
|
||||||
|
return assign(Self(other.ptr, size_in_bytes, base));
|
||||||
|
return assign(Self(other.ptr, other.size_in_bytes, other.base));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// nullptr
|
||||||
|
CSelf(std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, SpanSizeInBytes, const void *) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, SpanCount, const void *) SPAN_DELETED_FUNCTION;
|
||||||
|
CSelf(std::nullptr_t, size_type, const void *) SPAN_DELETED_FUNCTION;
|
||||||
|
Self &operator=(std::nullptr_t) SPAN_DELETED_FUNCTION;
|
||||||
|
#if 0
|
||||||
|
// don't enable, this prevents generic usage
|
||||||
|
bool operator==(std::nullptr_t) const SPAN_DELETED_FUNCTION;
|
||||||
|
bool operator!=(std::nullptr_t) const SPAN_DELETED_FUNCTION;
|
||||||
|
#else
|
||||||
|
bool operator==(std::nullptr_t) const {
|
||||||
|
assertInvariants();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool operator!=(std::nullptr_t) const {
|
||||||
|
assertInvariants();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#undef CSelf
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T *raw_bytes(const Span<T> &a, size_t size_in_bytes) {
|
||||||
|
return a.raw_bytes(size_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
SPAN_NAMESPACE_END
|
||||||
|
|
||||||
|
#if !SPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1
|
||||||
|
|
||||||
|
#define C SPAN_NS(Span)
|
||||||
|
#define D SPAN_NS(PtrOrSpanOrNull)
|
||||||
|
#define E SPAN_NS(PtrOrSpan)
|
||||||
|
#include "xspan_fwd.h"
|
||||||
|
#undef C
|
||||||
|
#undef D
|
||||||
|
#undef E
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
||||||
20
src/work.cpp
20
src/work.cpp
@ -190,15 +190,15 @@ void do_one_file(const char *iname, char *oname) {
|
|||||||
r = chmod(iname, 0777);
|
r = chmod(iname, 0777);
|
||||||
IGNORE_ERROR(r);
|
IGNORE_ERROR(r);
|
||||||
#endif
|
#endif
|
||||||
File::unlink(iname);
|
FileBase::unlink(iname);
|
||||||
} else {
|
} else {
|
||||||
// make backup
|
// make backup
|
||||||
char bakname[ACC_FN_PATH_MAX + 1];
|
char bakname[ACC_FN_PATH_MAX + 1];
|
||||||
if (!makebakname(bakname, sizeof(bakname), iname))
|
if (!makebakname(bakname, sizeof(bakname), iname))
|
||||||
throwIOException("could not create a backup file name");
|
throwIOException("could not create a backup file name");
|
||||||
File::rename(iname, bakname);
|
FileBase::rename(iname, bakname);
|
||||||
}
|
}
|
||||||
File::rename(oname, iname);
|
FileBase::rename(oname, iname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy file attributes
|
// copy file attributes
|
||||||
@ -272,40 +272,40 @@ int do_files(int i, int argc, char *argv[]) {
|
|||||||
if (opt->verbose >= 1 || (opt->verbose >= 0 && !e.isWarning()))
|
if (opt->verbose >= 1 || (opt->verbose >= 0 && !e.isWarning()))
|
||||||
printErr(iname, &e);
|
printErr(iname, &e);
|
||||||
main_set_exit_code(e.isWarning() ? EXIT_WARN : EXIT_ERROR);
|
main_set_exit_code(e.isWarning() ? EXIT_WARN : EXIT_ERROR);
|
||||||
// continue processing more files
|
// this is not fatal, continue processing more files
|
||||||
} catch (const Error &e) {
|
} catch (const Error &e) {
|
||||||
unlink_ofile(oname);
|
unlink_ofile(oname);
|
||||||
printErr(iname, &e);
|
printErr(iname, &e);
|
||||||
main_set_exit_code(EXIT_ERROR);
|
main_set_exit_code(EXIT_ERROR);
|
||||||
return -1;
|
return -1; // fatal error
|
||||||
} catch (std::bad_alloc *e) {
|
} catch (std::bad_alloc *e) {
|
||||||
unlink_ofile(oname);
|
unlink_ofile(oname);
|
||||||
printErr(iname, "out of memory");
|
printErr(iname, "out of memory");
|
||||||
UNUSED(e);
|
UNUSED(e);
|
||||||
// delete e;
|
// delete e;
|
||||||
main_set_exit_code(EXIT_ERROR);
|
main_set_exit_code(EXIT_ERROR);
|
||||||
return -1;
|
return -1; // fatal error
|
||||||
} catch (const std::bad_alloc &) {
|
} catch (const std::bad_alloc &) {
|
||||||
unlink_ofile(oname);
|
unlink_ofile(oname);
|
||||||
printErr(iname, "out of memory");
|
printErr(iname, "out of memory");
|
||||||
main_set_exit_code(EXIT_ERROR);
|
main_set_exit_code(EXIT_ERROR);
|
||||||
return -1;
|
return -1; // fatal error
|
||||||
} catch (std::exception *e) {
|
} catch (std::exception *e) {
|
||||||
unlink_ofile(oname);
|
unlink_ofile(oname);
|
||||||
printUnhandledException(iname, e);
|
printUnhandledException(iname, e);
|
||||||
// delete e;
|
// delete e;
|
||||||
main_set_exit_code(EXIT_ERROR);
|
main_set_exit_code(EXIT_ERROR);
|
||||||
return -1;
|
return -1; // fatal error
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
unlink_ofile(oname);
|
unlink_ofile(oname);
|
||||||
printUnhandledException(iname, &e);
|
printUnhandledException(iname, &e);
|
||||||
main_set_exit_code(EXIT_ERROR);
|
main_set_exit_code(EXIT_ERROR);
|
||||||
return -1;
|
return -1; // fatal error
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
unlink_ofile(oname);
|
unlink_ofile(oname);
|
||||||
printUnhandledException(iname, nullptr);
|
printUnhandledException(iname, nullptr);
|
||||||
main_set_exit_code(EXIT_ERROR);
|
main_set_exit_code(EXIT_ERROR);
|
||||||
return -1;
|
return -1; // fatal error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user