Bug#926118: Alternative for unblock: libmspack/0.10.1-1
Hi all,
first off, many thanks for your efforts here, Paul!
On 06.06.19 15:54, Paul Gevers wrote:
> On 06-06-2019 04:23, Marc Dequènes (duck) wrote:
>> I'm not committing to this plan for the above stated reasons. I also
>> feels uncomfortable uploading with a know security problem, so unless
>> upstream or our security team says it's low risk, I'm not taking such
>> responsibility.
>
> Sorry, I am mising something here. Can you please point me to it again?
AFAICT duck had this in his original unblock request:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=923885#5:
> Please unblock package libmspack. 0.9.1-1 should have made it
> but somehow the build failed on big-endian systems (see #914794),
> maybe gcc changes in the meanwhile; anyway upstream kindly fixed
> it but it took some time.
>
> 0.10.1 is a maintenance release with only few fixes, among which
> fixing chmd_read_headers() closed a security problem (see upstream
> ChangeLog in debdiff). There is also a simple one-liner fix for
> the doc (compared to 0.9.1-1, which had ample time to be tested).
> I would also note that 0.9.1-1 fixed a regression (see #912687).
> Thus I believe 0.10.1-1 is a much better fit for release and hope
> you would conclude the same.
The referenced ChangeLog was:
2019-02-18 Stuart Caie <kyzer@cabextract.org.uk>:
> chmd_read_headers(): CHM files can declare their chunks are any
> size up to 4GB, and libmspack will attempt to allocate that to
> read the file.
>
> This is not a security issue; libmspack doesn't promise how
> much memory it'll use to unpack files. You can set your own
> limits by returning NULL in a custom mspack_system.alloc()
> implementation.
>
> However, it would be good to validate chunk size further. With
> no offical specification, only empirical data is available. All
> files created by hhc.exe have a chunk size of 4096 bytes, and
> this is matched by all the files I've found in the wild, except
> for one which has a chunk size of 8192 bytes, which was created
> by someone developing a CHM file creator 15 years ago, and they
> appear to have abandoned it, so it seems 4096 is a de-facto
> standard.
>
> I've changed the "chunk size is not a power of two" warning to
> "chunk size is not 4096", and now only allow chunk sizes between
> 22 and 8192 bytes. If you have CHM files with a larger chunk
> size, please send them to me and I'll increase this upper limit.
>
> Thanks to ADLab of Venustech for the report.
On 06.06.19 15:54, Paul Gevers wrote:
> On 06-06-2019 04:23, Marc Dequènes (duck) wrote:
>> On 2019-06-04 03:53, Paul Gevers wrote:
>> Currently the current version has been sitting in unstable for three
>> months without any single bug reported, this feels like a good progress
>> towards saying this version is safe.
>
> It's a valid argument for sure.
And the previous 0.9.1-1 is even 7 months old now, having been blocked
only by the big endian issue. Personally I doubt an in-depth code
review is really helpful here. Anyway, I'm attaching 2 new debdiffs:
Upstream did a "tab to spaces". A "debdiff --ignore-space" reduces the
diff from 11176 to 4819 lines. I think this is also a point for
0.10.1-1 in buster, because it will make eventual security updates easier.
I further removed the diff of generated, examples and test files (I
marked those files in the diffstat). Yay, the diff had 678 lines
improving the tests!
I did this both for each 0.8-1 (in the archive since 2018-10-24) and
0.9.1-1 (2018-11-06) compared to 0.10.1-1 (2019-03-05).
So if at all, I'd suggest to only have a look at the last one of these
diffs:
$ wc -l debdiff_libmspack_0.*
11176 debdiff_libmspack_0.8-1_0.10.1-1.diff
4819 debdiff_libmspack_0.8-1_0.10.1-1_ignore-space.diff
1724 debdiff_libmspack_0.8-1_0.10.1-1_ignore-space_edited.diff
1067 debdiff_libmspack_0.9.1-1_0.10.1-1_ignore-space.diff
731 debdiff_libmspack_0.9.1-1_0.10.1-1_ignore-space_edited.diff
Thanks again and greets
jre
diffstat for libmspack-0.8 libmspack-0.10.1
ChangeLog | 107 +
Makefile.am | 66
-Makefile.in | 737 +++++++---
README | 17
acinclude.m4 | 12
config.h.in | 27
-configure | 402 +++--
configure.ac | 20
debian/changelog | 18
debian/control | 2
debian/copyright | 2
debian/libmspack-doc.docs | 12
debian/rules | 2
doc/.gitignore | 1
-doc/Doxyfile | 17
doc/Doxyfile.in | 22
-doc/Makefile | 16
doc/Makefile.in | 14
-examples/cabrip.c | 85 +
-examples/chmextract.c | 121 +
-examples/msexpand.c | 48
-examples/oabextract.c | 41
-libmscabd.la (Generated by libtool) | 41
-libmschmd.la (Generated by libtool) | 41
-libmspack.la (Generated by libtool) | 41
mspack/cab.h | 6
mspack/cabd.c | 67
mspack/chmd.c | 60
mspack/mspack.h | 31
mspack/oab.h | 1
mspack/oabd.c | 85 -
mspack/system.c | 5
mspack/system.h | 54
mspack/szddd.c | 4
src/cabrip.c | 85 -
src/chmextract.c | 122 -
src/error.h | 22
src/msexpand.c | 48
src/oabextract.c | 41
-test-driver | 148 ++
-test/cabd_test.c | 297 ++--
-test/chmd_test.c | 66
-test/chminfo.c | 7
-test/kwajd_test.c | 144 -
-test/md5.c | 7
-test/md5.h | 9
-test/test_files/cabd/mszip_lzx_qtm.cab |binary
-test/test_files/cabd/normal_2files_2folders.cab |binary
-test/test_files/chmd/cve-2015-4467-reset-interval-zero.chm.LZXC-is-lzxc |binary
-test/test_files/chmd/cve-2015-4467-reset-interval-zero.chm.xor |binary
-test/test_files/chmd/short-system-filenames.chm |binary
51 files changed, 1995 insertions(+), 1226 deletions(-)
diff -Nru -w libmspack-0.8/acinclude.m4 libmspack-0.10.1/acinclude.m4
--- libmspack-0.8/acinclude.m4 2017-08-13 21:38:18.000000000 +0200
+++ libmspack-0.10.1/acinclude.m4 2018-10-30 11:56:24.000000000 +0100
@@ -1,5 +1,5 @@
# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_func_mkdir.html
+# https://www.gnu.org/software/autoconf-archive/ax_func_mkdir.html
# ===========================================================================
#
# SYNOPSIS
@@ -43,7 +43,7 @@
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
+# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
@@ -58,19 +58,19 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
-#serial 4
+#serial 6
AU_ALIAS([AC_FUNC_MKDIR], [AX_FUNC_MKDIR])
AC_DEFUN([AX_FUNC_MKDIR],
[AC_CHECK_FUNCS([mkdir _mkdir])
AC_CACHE_CHECK([whether mkdir takes one argument],
[ac_cv_mkdir_takes_one_arg],
-[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/stat.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
-], [mkdir (".");])],
+]], [[mkdir (".");]])],
[ac_cv_mkdir_takes_one_arg=yes], [ac_cv_mkdir_takes_one_arg=no])])
if test x"$ac_cv_mkdir_takes_one_arg" = xyes; then
AC_DEFINE([MKDIR_TAKES_ONE_ARG], 1,
@@ -91,7 +91,7 @@
dnl |
dnl |Alexandre:
dnl | Would it be sufficient to check for these headers and #include
-dnl | them in the AC_TRY_COMPILE block? (and is AC_HEADER_DIRENT
+dnl | them in the AC_COMPILE_IFELSE block? (and is AC_HEADER_DIRENT
dnl | suitable for this?)
dnl |
dnl |Thomas:
diff -Nru -w libmspack-0.8/ChangeLog libmspack-0.10.1/ChangeLog
--- libmspack-0.8/ChangeLog 2018-10-20 20:04:29.000000000 +0200
+++ libmspack-0.10.1/ChangeLog 2019-02-18 21:01:59.000000000 +0100
@@ -1,3 +1,110 @@
+2019-02-18 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * chmd_read_headers(): a CHM file name beginning "::" but shorter
+ than 33 bytes will lead to reading past the freshly-allocated name
+ buffer - checks for specific control filenames didn't take length
+ into account. Thanks to ADLab of Venustech for the report and
+ proof of concept.
+
+2019-02-18 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * chmd_read_headers(): CHM files can declare their chunks are any
+ size up to 4GB, and libmspack will attempt to allocate that to
+ read the file.
+
+ This is not a security issue; libmspack doesn't promise how much
+ memory it'll use to unpack files. You can set your own limits by
+ returning NULL in a custom mspack_system.alloc() implementation.
+
+ However, it would be good to validate chunk size further. With no
+ offical specification, only empirical data is available. All files
+ created by hhc.exe have a chunk size of 4096 bytes, and this is
+ matched by all the files I've found in the wild, except for one
+ which has a chunk size of 8192 bytes, which was created by someone
+ developing a CHM file creator 15 years ago, and they appear to
+ have abandoned it, so it seems 4096 is a de-facto standard.
+
+ I've changed the "chunk size is not a power of two" warning to
+ "chunk size is not 4096", and now only allow chunk sizes between
+ 22 and 8192 bytes. If you have CHM files with a larger chunk size,
+ please send them to me and I'll increase this upper limit.
+
+ Thanks to ADLab of Venustech for the report.
+
+2019-02-18 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * oabd.c: replaced one-shot copying of uncompressed blocks (which
+ requires allocating a buffer of the size declared in the header,
+ which can be 4GB) with a fixed-size buffer. The buffer size is
+ user-controllable with the new msoab_decompressor::set_param()
+ method (check you have version 2 of the OAB decompressor), and
+ also controls the input buffer used for OAB's LZX decompression.
+
+ Reminder: compression formats can dictate how much memory is
+ needed to decompress them. If memory usage is a security concern
+ to you, write a custom mspack_system.alloc() that returns NULL
+ if "too much" memory is requested. Do not rely on libmspack adding
+ special heuristics to know not to request "too much".
+
+ Thanks to ADLab of Venustech for the report.
+
+2018-11-03 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * configure.ac, doc/Makefile.in, doc/Doxyfile.in: remove these
+ template files and replace with static files. You can still build
+ the documentation with make -C doc
+
+2018-11-03 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * Makefile.am, src: move the "useful" programs in src/ to examples/
+ and don't auto-install them. Even though they're useful, they are
+ intended as examples and aren't productised (no commmand-line
+ options, no man pages, etc.) -- if you disagree, feel free to
+ send in a patch
+
+2018-11-01 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * cabd_extract(): would not do decompression for random-access
+ offsets if the folder type was LZX. This is a fairly major bug,
+ and affects any decompression where you skip directly to a file,
+ or decompress data out-of-order. Thanks to austin987 for alerting
+ me to this.
+
+ This bug was introduced by the recent 'salvage mode' patch. Even
+ though I'd reviewed all the differences in clamav's copy of
+ libmspack and said "wtf" to this particular change, I didn't
+ notice it was still in the resulting patch I merged. Mea culpa :)
+
+ * test/cabd_test.c: now has a regression test to cover this
+
+2018-10-31 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * Makefile.am, test/*_test.c: use the automake test-suite system
+ with the test-suite programs (cabd_test, chmd_test, kwajd_test).
+ This also fixes a longstanding bugbear that these programs don't
+ access their test files using an absolute path. Now this is passed
+ to them and you can run them from any directory. Thanks to Richard
+ Jones for requesting this.
+
+2018-10-31 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * configure.ac: require at least automake 1.11, use AM_SILENT_RULES
+ unconditionally
+
+2018-10-30 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * configure.ac: remove obsolescent C library tests. AC_HEADER_STDC is
+ removed, and so are most checks for standard C headers. libmspack now
+ makes these assumptions:
+ - <ctype.h> <limits.h> <stdlib.h> <string.h> exist
+ - <ctype.h> defines tolower()
+ - <string.h> defines memset(), memcmp(), strlen()
+ - if towlower() exists, it's defined in <wctype.h>
+
+2018-10-22 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * cabd.c: remove the only use of assert()
+
2018-10-20 Stuart Caie <kyzer@cabextract.org.uk>
* src/chmextract.c: add anti "../" and leading slash protection to
diff -Nru -w libmspack-0.8/config.h.in libmspack-0.10.1/config.h.in
--- libmspack-0.8/config.h.in 2018-10-21 17:51:13.000000000 +0200
+++ libmspack-0.10.1/config.h.in 2019-03-04 10:39:16.000000000 +0100
@@ -1,11 +1,11 @@
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
/* Turn debugging mode on? */
#undef DEBUG
-/* Define to 1 if you have the <ctype.h> header file. */
-#undef HAVE_CTYPE_H
-
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
@@ -15,9 +15,6 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
-/* Define to 1 if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
-
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@@ -42,18 +39,12 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
-/* Define to 1 if you have the `tolower' function. */
-#undef HAVE_TOLOWER
-
/* Define to 1 if you have the `towlower' function. */
#undef HAVE_TOWLOWER
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
-/* Define to 1 if you have the <wctype.h> header file. */
-#undef HAVE_WCTYPE_H
-
/* Define to 1 if you have the `_mkdir' function. */
#undef HAVE__MKDIR
@@ -93,6 +84,18 @@
/* Version number of package */
#undef VERSION
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
diff -Nru -w libmspack-0.8/configure.ac libmspack-0.10.1/configure.ac
--- libmspack-0.8/configure.ac 2018-10-21 17:49:47.000000000 +0200
+++ libmspack-0.10.1/configure.ac 2019-03-04 10:36:51.000000000 +0100
@@ -1,16 +1,13 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT([libmspack],[0.8alpha],[kyzer@cabextract.org.uk])
+AC_INIT([libmspack],[0.10.1alpha],[kyzer@cabextract.org.uk])
AC_CONFIG_MACRO_DIR([m4])
-AM_INIT_AUTOMAKE
+AM_INIT_AUTOMAKE([1.11])
+AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR([mspack/mspack.h])
AC_CONFIG_HEADER([config.h])
-dnl Enable silent rules by default (if yet support in automake)
-dnl use 'make V=1' to look at verbose commandline
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-
# --enable-debug option
AC_ARG_ENABLE(debug,
AS_HELP_STRING(--enable-debug,enable debugging),
@@ -19,7 +16,6 @@
if test x$enable_debug = xyes; then
AC_DEFINE(DEBUG, 1, [Turn debugging mode on?])
fi
-AM_CONDITIONAL(DEBUG, test x$enable_debug = 'xyes')
# Checks for programs.
AC_PROG_CC
@@ -27,15 +23,14 @@
AM_PROG_AR
AC_PROG_INSTALL
LT_INIT
-AC_EXEEXT
# Checks for header files.
-AC_HEADER_STDC
-AC_CHECK_HEADERS([ctype.h inttypes.h limits.h stdlib.h wctype.h])
+AC_CHECK_HEADERS([inttypes.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
+AC_C_BIGENDIAN
AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
@@ -43,12 +38,11 @@
# Checks for library functions
AX_FUNC_MKDIR
-AC_CHECK_FUNCS([tolower towlower])
+AC_CHECK_FUNCS([towlower])
# largefile support
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
-# Checks for library functions.
-AC_CONFIG_FILES([Makefile doc/Makefile doc/Doxyfile libmspack.pc])
+AC_CONFIG_FILES([Makefile libmspack.pc])
AC_OUTPUT
diff -Nru -w libmspack-0.8/debian/changelog libmspack-0.10.1/debian/changelog
--- libmspack-0.8/debian/changelog 2018-10-24 03:03:13.000000000 +0200
+++ libmspack-0.10.1/debian/changelog 2019-03-05 11:03:29.000000000 +0100
@@ -1,3 +1,21 @@
+libmspack (0.10.1-1) unstable; urgency=medium
+
+ * New upstream release:
+ + fix build on big-endian systems (Closes: #914794)
+ * Add missing JS files for documentation menu and search functions.
+
+ -- Marc Dequènes (Duck) <Duck@DuckCorp.org> Tue, 05 Mar 2019 19:03:29 +0900
+
+libmspack (0.9.1-1) unstable; urgency=medium
+
+ * New upstream release:
+ + fix regression when extracting cabinets using -F option
+ (Closes: #912687)
+ * Bump Standards-Version to 4.2.1.
+ * Adapt to documentation now generated in 'doc/html'.
+
+ -- Marc Dequènes (Duck) <Duck@DuckCorp.org> Tue, 06 Nov 2018 22:38:49 +0900
+
libmspack (0.8-1) unstable; urgency=medium
* New upstream release:
diff -Nru -w libmspack-0.8/debian/control libmspack-0.10.1/debian/control
--- libmspack-0.8/debian/control 2018-04-12 12:20:00.000000000 +0200
+++ libmspack-0.10.1/debian/control 2019-03-05 07:24:16.000000000 +0100
@@ -2,7 +2,7 @@
Section: libs
Priority: optional
Maintainer: Marc Dequènes (Duck) <Duck@DuckCorp.org>
-Standards-Version: 4.1.4
+Standards-Version: 4.2.1
Build-Depends: dpkg-dev (>= 1.16.1.1), debhelper (>= 11)
Build-Depends-indep: doxygen, graphviz
Vcs-Browser: https://salsa.debian.org/debian/libmspack
diff -Nru -w libmspack-0.8/debian/copyright libmspack-0.10.1/debian/copyright
--- libmspack-0.8/debian/copyright 2018-04-05 05:16:07.000000000 +0200
+++ libmspack-0.10.1/debian/copyright 2019-03-05 07:24:35.000000000 +0100
@@ -2,6 +2,8 @@
Upstream-Name: libmspack
Upstream-Contact: Stuart Caie <kyzer@4u.net>
Source: https://www.cabextract.org.uk/libmspack/
+# doxygen-generated doc which is embedded in the upstream tarball; regenerated in the Debian build
+Files-excluded: doc/html
Files: *
diff -Nru -w libmspack-0.8/debian/libmspack-doc.docs libmspack-0.10.1/debian/libmspack-doc.docs
--- libmspack-0.8/debian/libmspack-doc.docs 2018-04-05 05:16:07.000000000 +0200
+++ libmspack-0.10.1/debian/libmspack-doc.docs 2019-03-05 10:52:56.000000000 +0100
@@ -1,4 +1,8 @@
-doc/*.html
-doc/*.css
-doc/*.png
-doc/search
+doc/html/*.html
+doc/html/*.css
+doc/html/*.png
+# jquery.js is generated by doxygen
+# there is no easy way to replace it with a symlink to a system common version
+# rationale: /usr/share/doc/doxygen/README.jquery
+doc/html/*.js
+doc/html/search
diff -Nru -w libmspack-0.8/debian/rules libmspack-0.10.1/debian/rules
--- libmspack-0.8/debian/rules 2018-04-12 12:24:08.000000000 +0200
+++ libmspack-0.10.1/debian/rules 2019-03-05 10:50:48.000000000 +0100
@@ -15,8 +15,6 @@
override_dh_auto_clean:
[ -f doc/Makefile ] && $(MAKE) -C doc clean
- # not enough
- rm -rf doc/menu.js doc/menudata.js
dh_auto_clean
override_dh_strip:
diff -Nru -w libmspack-0.8/doc/Doxyfile.in libmspack-0.10.1/doc/Doxyfile.in
--- libmspack-0.8/doc/Doxyfile.in 2015-06-05 10:10:54.000000000 +0200
+++ libmspack-0.10.1/doc/Doxyfile.in 1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-PROJECT_NAME = libmspack
-OUTPUT_DIRECTORY = .
-EXTRACT_ALL = YES
-EXTRACT_LOCAL_CLASSES = YES
-HIDE_UNDOC_MEMBERS = YES
-SHOW_INCLUDE_FILES = YES
-JAVADOC_AUTOBRIEF = YES
-OPTIMIZE_OUTPUT_FOR_C = YES
-SHOW_USED_FILES = YES
-INPUT = @top_srcdir@/mspack/mspack.h
-FULL_PATH_NAMES = NO
-GENERATE_HTML = YES
-HTML_OUTPUT = .
-HTML_FILE_EXTENSION = .html
-HTML_TIMESTAMP = NO
-GENERATE_HTMLHELP = NO
-GENERATE_LATEX = NO
-GENERATE_RTF = NO
-GENERATE_MAN = NO
-GENERATE_XML = NO
-GENERATE_AUTOGEN_DEF = NO
-CLASS_DIAGRAMS = NO
diff -Nru -w libmspack-0.8/doc/.gitignore libmspack-0.10.1/doc/.gitignore
--- libmspack-0.8/doc/.gitignore 1970-01-01 01:00:00.000000000 +0100
+++ libmspack-0.10.1/doc/.gitignore 2018-11-04 00:53:53.000000000 +0100
@@ -0,0 +1,1 @@
+html
diff -Nru -w libmspack-0.8/doc/Makefile.in libmspack-0.10.1/doc/Makefile.in
--- libmspack-0.8/doc/Makefile.in 2017-11-26 12:58:55.000000000 +0100
+++ libmspack-0.10.1/doc/Makefile.in 1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
-DOCS = annotated.html classes.html dir_*.html doxygen.* dynsections.js \
- files.html functions*.html globals*.html graph_legend.html index.html \
- jquery.js mspack*.html search struct*.html tab* *.map *.md5 *.png
-
-all: index.html
-
-clean:
- -rm -rf $(DOCS) installdox
-
-index.html: @top_srcdir@/mspack/mspack.h Doxyfile
- doxygen
-
-mspack_docs.zip: index.html
- zip -9r $@ $(DOCS) szdd_kwaj_format.html
diff -Nru -w libmspack-0.8/Makefile.am libmspack-0.10.1/Makefile.am
--- libmspack-0.8/Makefile.am 2018-10-16 12:07:28.000000000 +0200
+++ libmspack-0.10.1/Makefile.am 2018-11-06 12:14:30.000000000 +0100
@@ -1,30 +1,26 @@
AUTOMAKE_OPTIONS = subdir-objects
-EXTRA_DIST = $(srcdir)/debian/* $(srcdir)/doc/* $(srcdir)/test/test_files/*/*
+EXTRA_DIST = doc test/test_files
pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libmspack.pc
-
-dist-hook:
- -rm -f $(distdir)/*.la
+TESTS = $(check_PROGRAMS)
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS =
# add "-DMSPACK_NO_DEFAULT_SYSTEM" to remove default mspack_system
-if DEBUG
-AM_CFLAGS += -DDEBUG
-endif
if GCC
AM_CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wno-unused-result
endif
-AM_CPPFLAGS = -I$(top_srcdir)/mspack -I$(top_srcdir)/test
+AM_CPPFLAGS = -I$(srcdir)/mspack -I$(srcdir)/test
-bin_PROGRAMS = src/cabrip src/chmextract src/msexpand src/oabextract
include_HEADERS = mspack/mspack.h
lib_LTLIBRARIES = libmspack.la
+pkgconfig_DATA = libmspack.pc
noinst_LTLIBRARIES = libmscabd.la libmschmd.la
-noinst_PROGRAMS = examples/cabd_memory examples/multifh test/cabd_md5 \
- test/cabd_test test/chmd_find test/chmd_md5 \
- test/chmd_order test/chmd_test test/chminfo test/kwajd_test
+noinst_PROGRAMS = examples/cabd_memory examples/cabrip examples/chmextract \
+ examples/msexpand examples/multifh examples/oabextract \
+ test/cabd_md5 test/chmd_find test/chmd_md5 test/chmd_order \
+ test/chminfo
+check_PROGRAMS = test/cabd_test test/chmd_test test/kwajd_test
libmspack_la_SOURCES = mspack/mspack.h \
mspack/system.h mspack/system.c \
@@ -42,7 +38,7 @@
mspack/lzss.h mspack/lzssd.c \
mspack/des.h mspack/sha.h \
mspack/crc32.c mspack/crc32.h
-libmspack_la_LDFLAGS = -export-symbols-regex '^mspack_' -version-info 1:0:1
+libmspack_la_LDFLAGS = -export-symbols-regex '^mspack_' -version-info 1:0:1 -no-undefined
libmscabd_la_SOURCES = mspack/mspack.h \
mspack/system.h mspack/system.c \
@@ -62,38 +58,34 @@
examples_cabd_memory_SOURCES = examples/cabd_memory.c libmscabd.la
examples_cabd_memory_LDADD = libmscabd.la
+examples_cabrip_SOURCES = examples/cabrip.c libmspack.la
+examples_cabrip_LDADD = libmspack.la
+examples_chmextract_SOURCES = examples/chmextract.c test/error.h libmspack.la
+examples_chmextract_LDADD = libmspack.la
+examples_msexpand_SOURCES = examples/msexpand.c test/error.h libmspack.la
+examples_msexpand_LDADD = libmspack.la
examples_multifh_SOURCES = examples/multifh.c libmscabd.la
examples_multifh_LDADD = libmscabd.la
+examples_oabextract_SOURCES = examples/oabextract.c test/error.h libmspack.la
+examples_oabextract_LDADD = libmspack.la
-src_cabrip_SOURCES = src/cabrip.c libmspack.la
-src_cabrip_LDADD = libmspack.la
-src_chmextract_SOURCES = src/chmextract.c src/error.h libmspack.la
-src_chmextract_LDADD = libmspack.la
-src_msexpand_SOURCES = src/msexpand.c src/error.h libmspack.la
-src_msexpand_LDADD = libmspack.la
-src_oabextract_SOURCES = src/oabextract.c src/error.h libmspack.la
-src_oabextract_LDADD = libmspack.la
-
-test_cabd_md5_SOURCES = test/cabd_md5.c test/md5.c test/md5.h \
- test/md5_fh.h test/error.h libmscabd.la
+test_cabd_md5_SOURCES = test/cabd_md5.c test/md5.c test/md5.h test/md5_fh.h test/error.h libmscabd.la
test_cabd_md5_LDADD = libmscabd.la
-test_cabd_test_SOURCES= test/cabd_test.c libmscabd.la
-test_cabd_test_LDADD = libmscabd.la
test_chmd_find_SOURCES = test/chmd_find.c test/error.h libmschmd.la
test_chmd_find_LDADD = libmschmd.la
-test_chmd_md5_SOURCES = test/chmd_md5.c test/md5.c test/md5.h \
- test/md5_fh.h test/error.h libmschmd.la
+test_chmd_md5_SOURCES = test/chmd_md5.c test/md5.c test/md5.h test/md5_fh.h test/error.h libmschmd.la
test_chmd_md5_LDADD = libmschmd.la
-test_chmd_order_SOURCES = test/chmd_order.c test/md5.c test/md5.h \
- test/md5_fh.h test/error.h libmschmd.la
+test_chmd_order_SOURCES = test/chmd_order.c test/md5.c test/md5.h test/md5_fh.h test/error.h libmschmd.la
test_chmd_order_LDADD = libmschmd.la
-test_chmd_test_SOURCES = test/chmd_test.c libmschmd.la
-test_chmd_test_LDADD = libmschmd.la
-test_chmd_test_DEPENDENCIES = libmschmd.la test/test_files/chmd/cve-2015-4467-reset-interval-zero.chm
test_chminfo_SOURCES = test/chminfo.c libmschmd.la
test_chminfo_LDADD = libmschmd.la
+
+test_cabd_test_SOURCES = test/cabd_test.c test/md5.c test/md5.h test/md5_fh.h libmscabd.la
+test_cabd_test_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_FILES=$(abs_srcdir)/test/test_files/cabd
+test_cabd_test_LDADD = libmscabd.la
+test_chmd_test_SOURCES = test/chmd_test.c test/md5.c test/md5.h test/md5_fh.h libmschmd.la
+test_chmd_test_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_FILES=$(abs_srcdir)/test/test_files/chmd
+test_chmd_test_LDADD = libmschmd.la
test_kwajd_test_SOURCES = test/kwajd_test.c libmspack.la
+test_kwajd_test_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_FILES=$(abs_srcdir)/test/test_files/kwajd
test_kwajd_test_LDADD = libmspack.la
-
-test/test_files/chmd/cve-2015-4467-reset-interval-zero.chm: test/test_files/chmd/cve-2015-4467-reset-interval-zero.chm.LZXC-is-lzxc
- sed s/lzxc/LZXC/ $< >$@
diff -Nru -w libmspack-0.8/mspack/cabd.c libmspack-0.10.1/mspack/cabd.c
--- libmspack-0.8/mspack/cabd.c 2018-10-21 17:45:07.000000000 +0200
+++ libmspack-0.10.1/mspack/cabd.c 2019-03-04 02:09:26.000000000 +0100
@@ -23,7 +23,9 @@
#include <system.h>
#include <cab.h>
-#include <assert.h>
+#include <mszip.h>
+#include <lzx.h>
+#include <qtm.h>
/* Notes on compliance with cabinet specification:
*
@@ -154,10 +156,10 @@
self->d = NULL;
self->error = MSPACK_ERR_OK;
- self->param[MSCABD_PARAM_SEARCHBUF] = 32768;
- self->param[MSCABD_PARAM_FIXMSZIP] = 0;
- self->param[MSCABD_PARAM_DECOMPBUF] = 4096;
- self->param[MSCABD_PARAM_SALVAGE] = 0;
+ self->searchbuf_size = 32768;
+ self->fix_mszip = 0;
+ self->buf_size = 4096;
+ self->salvage = 0;
}
return (struct mscab_decompressor *) self;
}
@@ -201,7 +203,7 @@
if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
if ((cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
cab->base.filename = filename;
- error = cabd_read_headers(sys, fh, cab, (off_t) 0, self->param[MSCABD_PARAM_SALVAGE], 0);
+ error = cabd_read_headers(sys, fh, cab, (off_t) 0, self->salvage, 0);
if (error) {
cabd_close(base, (struct mscabd_cabinet *) cab);
cab = NULL;
@@ -598,7 +600,7 @@
sys = self->system;
/* allocate a search buffer */
- search_buf = (unsigned char *) sys->alloc(sys, (size_t) self->param[MSCABD_PARAM_SEARCHBUF]);
+ search_buf = (unsigned char *) sys->alloc(sys, (size_t) self->searchbuf_size);
if (!search_buf) {
self->error = MSPACK_ERR_NOMEMORY;
return NULL;
@@ -647,7 +649,7 @@
struct mspack_system *sys = self->system;
unsigned char *p, *pend, state = 0;
unsigned int cablen_u32 = 0, foffset_u32 = 0;
- int false_cabs = 0, salvage = self->param[MSCABD_PARAM_SALVAGE];
+ int false_cabs = 0;
#if !LARGEFILE_SUPPORT
/* detect 32-bit off_t overflow */
@@ -662,8 +664,8 @@
/* search length is either the full length of the search buffer, or the
* amount of data remaining to the end of the file, whichever is less. */
length = flen - offset;
- if (length > self->param[MSCABD_PARAM_SEARCHBUF]) {
- length = self->param[MSCABD_PARAM_SEARCHBUF];
+ if (length > self->searchbuf_size) {
+ length = self->searchbuf_size;
}
/* fill the search buffer with data from disk */
@@ -673,9 +675,8 @@
/* FAQ avoidance strategy */
if ((offset == 0) && (EndGetI32(&buf[0]) == 0x28635349)) {
- sys->message(fh, "WARNING; found InstallShield header. "
- "This is probably an InstallShield file. "
- "Use UNSHIELD from www.synce.org to unpack it.");
+ sys->message(fh, "WARNING; found InstallShield header. Use unshield "
+ "(https://github.com/twogood/unshield) to unpack this file");
}
/* read through the entire buffer. */
@@ -728,14 +729,14 @@
* mode, don't check the alleged length, allow it to be garbage */
if ((foffset_u32 < cablen_u32) &&
((caboff + (off_t) foffset_u32) < (flen + 32)) &&
- (((caboff + (off_t) cablen_u32) < (flen + 32)) || salvage))
+ (((caboff + (off_t) cablen_u32) < (flen + 32)) || self->salvage))
{
/* likely cabinet found -- try reading it */
if (!(cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
return MSPACK_ERR_NOMEMORY;
}
cab->base.filename = filename;
- if (cabd_read_headers(sys, fh, cab, caboff, salvage, 1)) {
+ if (cabd_read_headers(sys, fh, cab, caboff, self->salvage, 1)) {
/* destroy the failed cabinet */
cabd_close((struct mscab_decompressor *) self,
(struct mscabd_cabinet *) cab);
@@ -1029,7 +1030,7 @@
*/
filelen = file->length;
if (filelen > CAB_LENGTHMAX || (file->offset + filelen) > CAB_LENGTHMAX) {
- if (self->param[MSCABD_PARAM_SALVAGE]) {
+ if (self->salvage) {
filelen = CAB_LENGTHMAX - file->offset;
}
else {
@@ -1047,7 +1048,7 @@
/* if file goes beyond what can be decoded, given an error.
* In salvage mode, don't assume block sizes, just try decoding
*/
- if (!self->param[MSCABD_PARAM_SALVAGE]) {
+ if (!self->salvage) {
off_t maxlen = fol->base.num_blocks * CAB_BLOCKMAX;
if ((file->offset + filelen) > maxlen) {
sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
@@ -1125,12 +1126,10 @@
* and pass back MSPACK_ERR_READ
*/
self->d->outfh = NULL;
- if ((self->d->comp_type & cffoldCOMPTYPE_MASK) != cffoldCOMPTYPE_LZX) {
if ((bytes = file->offset - self->d->offset)) {
error = self->d->decompress(self->d->state, bytes);
self->error = (error == MSPACK_ERR_READ) ? self->read_error : error;
}
- }
/* if getting to the correct offset was error free, unpack file */
if (!self->error) {
@@ -1161,31 +1160,27 @@
{
struct mspack_file *fh = (struct mspack_file *) self;
- assert(self && self->d);
-
self->d->comp_type = ct;
switch (ct & cffoldCOMPTYPE_MASK) {
case cffoldCOMPTYPE_NONE:
self->d->decompress = (int (*)(void *, off_t)) &noned_decompress;
- self->d->state = noned_init(&self->d->sys, fh, fh,
- self->param[MSCABD_PARAM_DECOMPBUF]);
+ self->d->state = noned_init(&self->d->sys, fh, fh, self->buf_size);
break;
case cffoldCOMPTYPE_MSZIP:
self->d->decompress = (int (*)(void *, off_t)) &mszipd_decompress;
- self->d->state = mszipd_init(&self->d->sys, fh, fh,
- self->param[MSCABD_PARAM_DECOMPBUF],
- self->param[MSCABD_PARAM_FIXMSZIP]);
+ self->d->state = mszipd_init(&self->d->sys, fh, fh, self->buf_size,
+ self->fix_mszip);
break;
case cffoldCOMPTYPE_QUANTUM:
self->d->decompress = (int (*)(void *, off_t)) &qtmd_decompress;
self->d->state = qtmd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f,
- self->param[MSCABD_PARAM_DECOMPBUF]);
+ self->buf_size);
break;
case cffoldCOMPTYPE_LZX:
self->d->decompress = (int (*)(void *, off_t)) &lzxd_decompress;
self->d->state = lzxd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f, 0,
- self->param[MSCABD_PARAM_DECOMPBUF], (off_t)0,0);
+ self->buf_size, (off_t)0,0);
break;
default:
return self->error = MSPACK_ERR_DATAFORMAT;
@@ -1224,10 +1219,10 @@
struct mspack_system *sys = self->system;
int avail, todo, outlen, ignore_cksum, ignore_blocksize;
- ignore_cksum = self->param[MSCABD_PARAM_SALVAGE] ||
- (self->param[MSCABD_PARAM_FIXMSZIP] &&
+ ignore_cksum = self->salvage ||
+ (self->fix_mszip &&
((self->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP));
- ignore_blocksize = self->param[MSCABD_PARAM_SALVAGE];
+ ignore_blocksize = self->salvage;
todo = bytes;
while (todo > 0) {
@@ -1247,7 +1242,7 @@
/* check if we're out of input blocks, advance block counter */
if (self->d->block++ >= self->d->folder->base.num_blocks) {
- if (!self->param[MSCABD_PARAM_SALVAGE]) {
+ if (!self->salvage) {
self->read_error = MSPACK_ERR_DATAFORMAT;
}
else {
@@ -1484,17 +1479,17 @@
switch (param) {
case MSCABD_PARAM_SEARCHBUF:
if (value < 4) return MSPACK_ERR_ARGS;
- self->param[MSCABD_PARAM_SEARCHBUF] = value;
+ self->searchbuf_size = value;
break;
case MSCABD_PARAM_FIXMSZIP:
- self->param[MSCABD_PARAM_FIXMSZIP] = value;
+ self->fix_mszip = value;
break;
case MSCABD_PARAM_DECOMPBUF:
if (value < 4) return MSPACK_ERR_ARGS;
- self->param[MSCABD_PARAM_DECOMPBUF] = value;
+ self->buf_size = value;
break;
case MSCABD_PARAM_SALVAGE:
- self->param[MSCABD_PARAM_SALVAGE] = value;
+ self->salvage = value;
break;
default:
return MSPACK_ERR_ARGS;
diff -Nru -w libmspack-0.8/mspack/cab.h libmspack-0.10.1/mspack/cab.h
--- libmspack-0.8/mspack/cab.h 2018-10-21 17:44:47.000000000 +0200
+++ libmspack-0.10.1/mspack/cab.h 2019-03-04 10:09:35.000000000 +0100
@@ -10,10 +10,6 @@
#ifndef MSPACK_CAB_H
#define MSPACK_CAB_H 1
-#include <mszip.h>
-#include <qtm.h>
-#include <lzx.h>
-
/* generic CAB definitions */
/* structure offsets */
@@ -117,7 +113,7 @@
struct mscab_decompressor base;
struct mscabd_decompress_state *d;
struct mspack_system *system;
- int param[4]; /* !!! MATCH THIS TO NUM OF PARAMS IN MSPACK.H !!! */
+ int buf_size, searchbuf_size, fix_mszip, salvage; /* params */
int error, read_error;
};
diff -Nru -w libmspack-0.8/mspack/chmd.c libmspack-0.10.1/mspack/chmd.c
--- libmspack-0.8/mspack/chmd.c 2018-10-17 12:24:53.000000000 +0200
+++ libmspack-0.10.1/mspack/chmd.c 2019-03-04 02:10:28.000000000 +0100
@@ -44,7 +44,7 @@
struct mschm_decompressor_p *self, struct mschmd_file *file);
static int read_reset_table(
struct mschm_decompressor_p *self, struct mschmd_sec_mscompressed *sec,
- int entry, off_t *length_ptr, off_t *offset_ptr);
+ unsigned int entry, off_t *length_ptr, off_t *offset_ptr);
static int read_spaninfo(
struct mschm_decompressor_p *self, struct mschmd_sec_mscompressed *sec,
off_t *length_ptr);
@@ -292,7 +292,7 @@
}
/* check both header GUIDs */
- if (mspack_memcmp(&buf[chmhead_GUID1], &guids[0], 32L) != 0) {
+ if (memcmp(&buf[chmhead_GUID1], &guids[0], 32L) != 0) {
D(("incorrect GUIDs"))
return MSPACK_ERR_SIGNATURE;
}
@@ -381,14 +381,18 @@
D(("more than 100,000 chunks"))
return MSPACK_ERR_DATAFORMAT;
}
+ if (chm->chunk_size > 8192) {
+ D(("chunk size over 8192 (get in touch if this is valid)"))
+ return MSPACK_ERR_DATAFORMAT;
+ }
if ((off_t)chm->chunk_size * (off_t)chm->num_chunks > chm->length) {
D(("chunks larger than entire file"))
return MSPACK_ERR_DATAFORMAT;
}
/* common sense checks on header section 1 fields */
- if ((chm->chunk_size & (chm->chunk_size - 1)) != 0) {
- sys->message(fh, "WARNING; chunk size is not a power of two");
+ if (chm->chunk_size != 4096) {
+ sys->message(fh, "WARNING; chunk size is not 4096");
}
if (chm->first_pmgl != 0) {
sys->message(fh, "WARNING; first PMGL chunk is not zero");
@@ -435,7 +439,7 @@
sys->message(fh, "WARNING; PMGL quickref area is too small");
}
if (EndGetI32(&chunk[pmgl_QuickRefSize]) >
- ((int)chm->chunk_size - pmgl_Entries))
+ (chm->chunk_size - pmgl_Entries))
{
sys->message(fh, "WARNING; PMGL quickref area is too large");
}
@@ -483,20 +487,18 @@
if (name[0] == ':' && name[1] == ':') {
/* system file */
- if (mspack_memcmp(&name[2], &content_name[2], 31L) == 0) {
- if (mspack_memcmp(&name[33], &content_name[33], 8L) == 0) {
+ if (name_len == 40 && memcmp(name, content_name, 40) == 0) {
chm->sec1.content = fi;
}
- else if (mspack_memcmp(&name[33], &control_name[33], 11L) == 0) {
+ else if (name_len == 44 && memcmp(name, control_name, 44) == 0) {
chm->sec1.control = fi;
}
- else if (mspack_memcmp(&name[33], &spaninfo_name[33], 8L) == 0) {
+ else if (name_len == 41 && memcmp(name, spaninfo_name, 41) == 0) {
chm->sec1.spaninfo = fi;
}
- else if (mspack_memcmp(&name[33], &rtable_name[33], 72L) == 0) {
+ else if (name_len == 105 && memcmp(name, rtable_name, 105) == 0) {
chm->sec1.rtable = fi;
}
- }
fi->next = chm->sysfiles;
chm->sysfiles = fi;
}
@@ -536,7 +538,10 @@
struct mschm_decompressor_p *self = (struct mschm_decompressor_p *) base;
struct mspack_system *sys;
struct mspack_file *fh;
- const unsigned char *chunk, *p, *end;
+ /* p and end are initialised to prevent MSVC warning about "potentially"
+ * uninitialised usage. This is provably untrue, but MS won't fix:
+ * https://developercommunity.visualstudio.com/content/problem/363489/c4701-false-positive-warning.html */
+ const unsigned char *chunk, *p = NULL, *end = NULL;
int err = MSPACK_ERR_OK, result = -1;
unsigned int n, sec;
@@ -586,7 +591,7 @@
}
/* stop simple infinite loops: can't visit the same chunk twice */
- if ((int)n == EndGetI32(&chunk[pmgl_NextChunk])) {
+ if (n == EndGetI32(&chunk[pmgl_NextChunk])) {
break;
}
}
@@ -824,35 +829,11 @@
}
#if HAVE_TOWLOWER
-# if HAVE_WCTYPE_H
# include <wctype.h>
-# endif
# define TOLOWER(x) towlower(x)
-#elif HAVE_TOLOWER
-# if HAVE_CTYPE_H
+#else
# include <ctype.h>
-# endif
# define TOLOWER(x) tolower(x)
-#else
-# define TOLOWER(x) (((x)<0||(x)>255)?(x):mspack_tolower_map[(x)])
-/* Map of char -> lowercase char for the first 256 chars. Generated with:
- * LC_CTYPE=en_GB.utf-8 perl -Mlocale -le 'print map{ord(lc chr).","} 0..255'
- */
-static const unsigned char mspack_tolower_map[256] = {
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
- 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
- 53,54,55,56,57,58,59,60,61,62,63,64,97,98,99,100,101,102,103,104,105,106,
- 107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,
- 95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,
- 115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,
- 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,
- 153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,
- 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,
- 191,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,
- 242,243,244,245,246,215,248,249,250,251,252,253,254,223,224,225,226,227,228,
- 229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
- 248,249,250,251,252,253,254,255
-};
#endif
/* decodes a UTF-8 character from s[] into c. Will not read past e.
@@ -1175,7 +1156,8 @@
*/
static int read_reset_table(struct mschm_decompressor_p *self,
struct mschmd_sec_mscompressed *sec,
- int entry, off_t *length_ptr, off_t *offset_ptr)
+ unsigned int entry,
+ off_t *length_ptr, off_t *offset_ptr)
{
struct mspack_system *sys = self->system;
unsigned char *data;
diff -Nru -w libmspack-0.8/mspack/mspack.h libmspack-0.10.1/mspack/mspack.h
--- libmspack-0.8/mspack/mspack.h 2018-10-16 11:17:09.000000000 +0200
+++ libmspack-0.10.1/mspack/mspack.h 2019-02-18 21:25:16.000000000 +0100
@@ -1,5 +1,5 @@
/* libmspack -- a library for working with Microsoft compression formats.
- * (C) 2003-2016 Stuart Caie <kyzer@cabextract.org.uk>
+ * (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
@@ -1554,7 +1554,7 @@
*/
int (*set_param)(struct mschm_compressor *self,
int param,
- unsigned int value);
+ int value);
/**
* Returns the error code set by the most recently called method.
@@ -1853,7 +1853,7 @@
*/
int (*set_param)(struct msszdd_compressor *self,
int param,
- unsigned int value);
+ int value);
/**
* Returns the error code set by the most recently called method.
@@ -2091,7 +2091,7 @@
*/
int (*set_param)(struct mskwaj_compressor *self,
int param,
- unsigned int value);
+ int value);
/**
@@ -2353,8 +2353,31 @@
const char *input,
const char *base,
const char *output);
+
+ /**
+ * Sets an OAB decompression engine parameter. Available only in OAB
+ * decompressor version 2 and above.
+ *
+ * - #MSOABD_PARAM_DECOMPBUF: How many bytes should be used as an input
+ * buffer by decompressors? The minimum value is 16. The default value
+ * is 4096.
+ *
+ * @param self a self-referential pointer to the msoab_decompressor
+ * instance being called
+ * @param param the parameter to set
+ * @param value the value to set the parameter to
+ * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
+ * is a problem with either parameter or value.
+ */
+ int (*set_param)(struct msoab_decompressor *self,
+ int param,
+ int value);
+
};
+/** msoab_decompressor::set_param() parameter: size of decompression buffer */
+#define MSOABD_PARAM_DECOMPBUF (0)
+
#ifdef __cplusplus
}
#endif
diff -Nru -w libmspack-0.8/mspack/oabd.c libmspack-0.10.1/mspack/oabd.c
--- libmspack-0.8/mspack/oabd.c 2018-08-13 14:21:07.000000000 +0200
+++ libmspack-0.10.1/mspack/oabd.c 2019-03-04 10:11:49.000000000 +0100
@@ -33,6 +33,11 @@
static int oabd_decompress_incremental(struct msoab_decompressor *self,
const char *input, const char *base,
const char *output);
+static int oabd_param(struct msoab_decompressor *base, int param, int value);
+static int copy_fh(struct mspack_system *sys, struct mspack_file *infh,
+ struct mspack_file *outfh, size_t bytes_to_copy,
+ unsigned char *buf, int buf_size);
+
struct msoab_decompressor *
mspack_create_oab_decompressor(struct mspack_system *sys)
@@ -45,7 +50,9 @@
if ((self = (struct msoab_decompressor_p *) sys->alloc(sys, sizeof(struct msoab_decompressor_p)))) {
self->base.decompress = &oabd_decompress;
self->base.decompress_incremental = &oabd_decompress_incremental;
+ self->base.set_param = &oabd_param;
self->system = sys;
+ self->buf_size = 4096;
}
return (struct msoab_decompressor *) self;
}
@@ -132,17 +139,13 @@
block_max = EndGetI32(&hdrbuf[oabhead_BlockMax]);
target_size = EndGetI32(&hdrbuf[oabhead_TargetSize]);
- /* We use it for reading block headers too */
- if (block_max < oabblk_SIZEOF)
- block_max = oabblk_SIZEOF;
-
outfh = sys->open(sys, output, MSPACK_SYS_OPEN_WRITE);
if (!outfh) {
ret = MSPACK_ERR_OPEN;
goto out;
}
- buf = sys->alloc(sys, block_max);
+ buf = sys->alloc(sys, self->buf_size);
if (!buf) {
ret = MSPACK_ERR_NOMEMORY;
goto out;
@@ -181,14 +184,8 @@
ret = MSPACK_ERR_DATAFORMAT;
goto out;
}
- if (sys->read(infh, buf, blk_dsize) != (int)blk_dsize) {
- ret = MSPACK_ERR_READ;
- goto out;
- }
- if (sys->write(outfh, buf, blk_dsize) != (int)blk_dsize) {
- ret = MSPACK_ERR_WRITE;
- goto out;
- }
+ ret = copy_fh(sys, infh, outfh, blk_dsize, buf, self->buf_size);
+ if (ret) goto out;
} else {
/* LZX compressed block */
window_bits = 17;
@@ -200,7 +197,7 @@
out_ofh.crc = 0xffffffff;
lzx = lzxd_init(&oabd_sys, (void *)&in_ofh, (void *)&out_ofh, window_bits,
- 0, 4096, blk_dsize, 1);
+ 0, self->buf_size, blk_dsize, 1);
if (!lzx) {
ret = MSPACK_ERR_NOMEMORY;
goto out;
@@ -214,18 +211,8 @@
lzx = NULL;
/* Consume any trailing padding bytes before the next block */
- while (in_ofh.available) {
- int count = block_max;
- if ((size_t)count > in_ofh.available)
- count = in_ofh.available;
-
- count = sys->read(infh, buf, count);
- if (count < 0) {
- ret = MSPACK_ERR_READ;
- goto out;
- }
- in_ofh.available -= count;
- }
+ ret = copy_fh(sys, infh, NULL, in_ofh.available, buf, self->buf_size);
+ if (ret) goto out;
if (out_ofh.crc != blk_crc) {
ret = MSPACK_ERR_CHECKSUM;
@@ -301,7 +288,7 @@
goto out;
}
- buf = sys->alloc(sys, block_max);
+ buf = sys->alloc(sys, self->buf_size);
if (!buf) {
ret = MSPACK_ERR_NOMEMORY;
goto out;
@@ -364,18 +351,8 @@
lzx = NULL;
/* Consume any trailing padding bytes before the next block */
- while (in_ofh.available) {
- int count = block_max;
- if ((size_t)count > in_ofh.available)
- count = in_ofh.available;
-
- count = sys->read(infh, buf, count);
- if (count < 0) {
- ret = MSPACK_ERR_READ;
- goto out;
- }
- in_ofh.available -= count;
- }
+ ret = copy_fh(sys, infh, NULL, in_ofh.available, buf, self->buf_size);
+ if (ret) goto out;
if (out_ofh.crc != blk_crc) {
ret = MSPACK_ERR_CHECKSUM;
@@ -394,3 +371,33 @@
return ret;
}
+
+static int copy_fh(struct mspack_system *sys, struct mspack_file *infh,
+ struct mspack_file *outfh, size_t bytes_to_copy,
+ unsigned char *buf, int buf_size)
+{
+ while (bytes_to_copy) {
+ int run = buf_size;
+ if ((size_t) run > bytes_to_copy) {
+ run = (int) bytes_to_copy;
+ }
+ if (sys->read(infh, buf, run) != run) {
+ return MSPACK_ERR_READ;
+ }
+ if (outfh && sys->write(outfh, buf, run) != run) {
+ return MSPACK_ERR_WRITE;
+ }
+ bytes_to_copy -= run;
+ }
+ return MSPACK_ERR_OK;
+}
+
+static int oabd_param(struct msoab_decompressor *base, int param, int value) {
+ struct msoab_decompressor_p *self = (struct msoab_decompressor_p *) base;
+ if (self && param == MSOABD_PARAM_DECOMPBUF && value >= 16) {
+ /* must be at least 16 bytes (patchblk_SIZEOF, oabblk_SIZEOF) */
+ self->buf_size = value;
+ return MSPACK_ERR_OK;
+ }
+ return MSPACK_ERR_ARGS;
+}
diff -Nru -w libmspack-0.8/mspack/oab.h libmspack-0.10.1/mspack/oab.h
--- libmspack-0.8/mspack/oab.h 2017-11-26 15:11:38.000000000 +0100
+++ libmspack-0.10.1/mspack/oab.h 2019-02-18 17:39:40.000000000 +0100
@@ -27,6 +27,7 @@
struct msoab_decompressor_p {
struct msoab_decompressor base;
struct mspack_system *system;
+ int buf_size;
/* todo */
};
diff -Nru -w libmspack-0.8/mspack/system.c libmspack-0.10.1/mspack/system.c
--- libmspack-0.8/mspack/system.c 2018-10-16 11:17:09.000000000 +0200
+++ libmspack-0.10.1/mspack/system.c 2019-02-18 17:26:17.000000000 +0100
@@ -31,12 +31,15 @@
* - added MSCABD_PARAM_SALVAGE
*/
case MSPACK_VER_MSCABD:
+ /* OAB decoder version 1 -> 2 changes:
+ * - added msoab_decompressor::set_param and MSOABD_PARAM_DECOMPBUF
+ */
+ case MSPACK_VER_MSOABD:
return 2;
case MSPACK_VER_LIBRARY:
case MSPACK_VER_SYSTEM:
case MSPACK_VER_MSSZDDD:
case MSPACK_VER_MSKWAJD:
- case MSPACK_VER_MSOABD:
return 1;
case MSPACK_VER_MSCABC:
case MSPACK_VER_MSCHMC:
diff -Nru -w libmspack-0.8/mspack/system.h libmspack-0.10.1/mspack/system.h
--- libmspack-0.8/mspack/system.h 2018-07-29 09:46:43.000000000 +0200
+++ libmspack-0.10.1/mspack/system.h 2019-03-04 02:10:28.000000000 +0100
@@ -1,5 +1,5 @@
/* This file is part of libmspack.
- * (C) 2003-2004 Stuart Caie.
+ * (C) 2003-2018 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
@@ -21,6 +21,9 @@
#include <mspack.h>
+/* assume <string.h> exists */
+#include <string.h>
+
/* fix for problem with GCC 4 and glibc (thanks to Ville Skytta)
* http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=150429
*/
@@ -54,10 +57,6 @@
* greater than 2GB is detected, an error message indicating the library
* can't support the file should be printed.
*/
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
#if HAVE_INTTYPES_H
# include <inttypes.h>
#else
@@ -67,10 +66,11 @@
# define PRIu32 "lu"
#endif
+#include <limits.h>
#if ((defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS >= 64) || \
(defined(FILESIZEBITS) && FILESIZEBITS >= 64) || \
- (defined(SIZEOF_OFF_T) && SIZEOF_OFF_T >= 8) || \
- defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE))
+ defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE) || \
+ SIZEOF_OFF_T >= 8)
# define LARGEFILE_SUPPORT 1
# define LD PRId64
# define LU PRIu64
@@ -81,20 +81,19 @@
#endif
/* endian-neutral reading of little-endian data */
-#define __egi32(a,n) ( ((((unsigned char *) a)[n+3]) << 24) | \
- ((((unsigned char *) a)[n+2]) << 16) | \
- ((((unsigned char *) a)[n+1]) << 8) | \
- ((((unsigned char *) a)[n+0])))
-#define EndGetI64(a) ((((unsigned long long int) __egi32(a,4)) << 32) | \
- ((unsigned int) __egi32(a,0)))
+#define __egi32(a,n) (((unsigned int) ((unsigned char *)(a))[n+3] << 24) | \
+ ((unsigned int) ((unsigned char *)(a))[n+2] << 16) | \
+ ((unsigned int) ((unsigned char *)(a))[n+1] << 8) | \
+ ((unsigned int) ((unsigned char *)(a))[n]))
+#define EndGetI64(a) (((unsigned long long int) __egi32(a,4) << 32) | __egi32(a,0))
#define EndGetI32(a) __egi32(a,0)
#define EndGetI16(a) ((((a)[1])<<8)|((a)[0]))
/* endian-neutral reading of big-endian data */
-#define EndGetM32(a) (((((unsigned char *) a)[0]) << 24) | \
- ((((unsigned char *) a)[1]) << 16) | \
- ((((unsigned char *) a)[2]) << 8) | \
- ((((unsigned char *) a)[3])))
+#define EndGetM32(a) (((unsigned int) ((unsigned char *)(a))[0] << 24) | \
+ ((unsigned int) ((unsigned char *)(a))[1] << 16) | \
+ ((unsigned int) ((unsigned char *)(a))[2] << 8) | \
+ ((unsigned int) ((unsigned char *)(a))[3]))
#define EndGetM16(a) ((((a)[0])<<8)|((a)[1]))
extern struct mspack_system *mspack_default_system;
@@ -106,27 +105,6 @@
/* validates a system structure */
extern int mspack_valid_system(struct mspack_system *sys);
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#if HAVE_STRING_H
-# include <string.h>
-#endif
-
-#if HAVE_MEMCMP
-# define mspack_memcmp memcmp
-#else
-/* inline memcmp() */
-static inline int mspack_memcmp(const void *s1, const void *s2, size_t n) {
- unsigned char *c1 = (unsigned char *) s1;
- unsigned char *c2 = (unsigned char *) s2;
- if (n == 0) return 0;
- while (--n && (*c1 == *c2)) c1++, c2++;
- return *c1 - *c2;
-}
-#endif
-
#ifdef __cplusplus
}
#endif
diff -Nru -w libmspack-0.8/mspack/szddd.c libmspack-0.10.1/mspack/szddd.c
--- libmspack-0.8/mspack/szddd.c 2018-08-13 14:21:53.000000000 +0200
+++ libmspack-0.10.1/mspack/szddd.c 2018-11-05 12:53:09.000000000 +0100
@@ -150,7 +150,7 @@
/* read and check signature */
if (sys->read(fh, buf, 8) != 8) return MSPACK_ERR_READ;
- if ((mspack_memcmp(buf, szdd_signature_expand, 8) == 0)) {
+ if ((memcmp(buf, szdd_signature_expand, 8) == 0)) {
/* common SZDD */
hdr->format = MSSZDD_FMT_NORMAL;
@@ -160,7 +160,7 @@
hdr->missing_char = buf[1];
hdr->length = EndGetI32(&buf[2]);
}
- else if ((mspack_memcmp(buf, szdd_signature_qbasic, 8) == 0)) {
+ else if ((memcmp(buf, szdd_signature_qbasic, 8) == 0)) {
/* special QBasic SZDD */
hdr->format = MSSZDD_FMT_QBASIC;
if (sys->read(fh, buf, 4) != 4) return MSPACK_ERR_READ;
diff -Nru -w libmspack-0.8/README libmspack-0.10.1/README
--- libmspack-0.8/README 2018-10-21 17:49:53.000000000 +0200
+++ libmspack-0.10.1/README 2019-03-04 10:36:57.000000000 +0100
@@ -1,4 +1,4 @@
-libmspack 0.8alpha
+libmspack 0.10.1alpha
The purpose of libmspack is to provide compressors and decompressors,
archivers and dearchivers for Microsoft compression formats: CAB, CHM, WIM,
@@ -43,7 +43,7 @@
In addition to gcc, you also need the following for building from repository:
- at least autoconf 2.57
-- at least automake 1.7
+- at least automake 1.11
- libtool
This is an alpha release. Unless you are in a position to package the
@@ -84,21 +84,18 @@
in-memory images, raw file descriptors, open file
handles and regular disk files
-src/cabrip.c - extracts any CAB files embedded in another file
-src/chmextract.c - extracts all files in a CHM file to disk
-src/msexpand.c - expands an SZDD or KWAJ file
-src/oabextract.c - extracts an Exchange Offline Address Book (.LZX) file
+examples/cabrip.c - extracts any CAB files embedded in another file
+examples/chmextract.c - extracts all files in a CHM file to disk
+examples/msexpand.c - expands an SZDD or KWAJ file
+examples/oabextract.c - extracts an Exchange Offline Address Book (.LZX) file
test/cabd_c10 - tests the CAB decompressor on the C10 collection
test/cabd_compare - compares libmspack with Microsoft's EXTRACT.EXE
test/cabd_md5 - shows MD5 checksums of all files in a CAB file/set
-test/cabd_test.c - regression tests for libmspack's CAB decompression
test/chmd_compare - compares libmspack with Microsoft's HH.EXE
-test/chmd_find.c - fast-finds a file within a CHM file.
+test/chmd_find.c - checks all files in a CHM file can be fast-found
test/chmd_md5.c - shows MD5 checksums of all files within a CHM file
test/chmd_order.c - extracts files in a CHM file in four different ways
-test/chmd_test.c - regression tests for libmspack's CHM decompression
-test/kwajd_test.c - regression tests for libmspack's KWAJ decompression
test/chminfo.c - prints verbose information about CHM file structures
test/msdecompile_md5 - runs Microsoft's HH.EXE -DECOMPILE via WINE
test/msextract_md5 - runs Microsoft's EXTRACT.EXE via WINE
diff -Nru -w libmspack-0.8/src/cabrip.c libmspack-0.10.1/src/cabrip.c
--- libmspack-0.8/src/cabrip.c 2018-10-21 14:26:01.000000000 +0200
+++ libmspack-0.10.1/src/cabrip.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,85 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <mspack.h>
-#include <system.h>
-
-#if HAVE_FSEEKO
-# define fseek fseeko
-#endif
-
-#define BUF_SIZE (1024*4096)
-char buf[BUF_SIZE];
-
-void rip(char *fname, off_t offset, unsigned int length) {
- static unsigned int counter = 1;
- struct stat st_buf;
- char outname[13];
- FILE *in = NULL, *out = NULL;
-
- /* find an unused output filename */
- do {
- snprintf(outname, 13, "%08u.cab", counter++);
- } while (stat(outname, &st_buf) == 0);
-
- printf("ripping %s offset %" LD " length %u to %s\n",
- fname, offset, length, outname);
-
- if (!(in = fopen(fname, "rb"))) {
- perror(fname);
- goto cleanup;
- }
- if (!(out = fopen(outname, "wb"))) {
- perror(outname);
- goto cleanup;
- }
- if (fseek(in, offset, SEEK_SET)) {
- fprintf(stderr, "%s: can't seek to cab offset %"LD"\n", fname, offset);
- goto cleanup;
- }
- while (length) {
- size_t run = (length > BUF_SIZE) ? BUF_SIZE : length;
- size_t actual = fread(&buf[0], 1, run, in);
- if (actual < run) {
- fprintf(stderr, "%s: file %u bytes shorter than expected\n",
- fname, length - (run - actual));
- length = run = actual;
- }
- if (fwrite(&buf[0], 1, run, out) != run) {
- perror(outname);
- break;
- }
- length -= run;
- }
-
-cleanup:
- if (in) fclose(in);
- if (out) fclose(out);
-}
-
-int main(int argc, char *argv[]) {
- struct mscab_decompressor *cabd;
- struct mscabd_cabinet *cab, *c;
- int err;
-
- MSPACK_SYS_SELFTEST(err);
- if (err) return 0;
-
- if ((cabd = mspack_create_cab_decompressor(NULL))) {
- cabd->set_param(cabd, MSCABD_PARAM_SALVAGE, 1);
- for (argv++; *argv; argv++) {
- if ((cab = cabd->search(cabd, *argv))) {
- for (c = cab; c; c = c->next) {
- rip(*argv, c->base_offset, c->length);
- }
- cabd->close(cabd, cab);
- }
- }
- mspack_destroy_cab_decompressor(cabd);
- }
- return 0;
-}
diff -Nru -w libmspack-0.8/src/chmextract.c libmspack-0.10.1/src/chmextract.c
--- libmspack-0.8/src/chmextract.c 2018-10-20 20:05:18.000000000 +0200
+++ libmspack-0.10.1/src/chmextract.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,122 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <mspack.h>
-#include <ctype.h>
-#include <sys/stat.h>
-
-#include <error.h>
-
-#if HAVE_MKDIR
-# if MKDIR_TAKES_ONE_ARG
-# define mkdir(a, b) mkdir(a)
-# endif
-#else
-# if HAVE__MKDIR
-# define mkdir(a, b) _mkdir(a)
-# else
-# error "Don't know how to create a directory on this system."
-# endif
-#endif
-
-mode_t user_umask;
-
-/**
- * Ensures that all directory components in a filepath exist. New directory
- * components are created, if necessary.
- *
- * @param path the filepath to check
- * @return non-zero if all directory components in a filepath exist, zero
- * if components do not exist and cannot be created
- */
-static int ensure_filepath(char *path) {
- struct stat st_buf;
- char *p;
- int ok;
-
- for (p = &path[1]; *p; p++) {
- if (*p != '/') continue;
- *p = '\0';
- ok = (stat(path, &st_buf) == 0) && S_ISDIR(st_buf.st_mode);
- if (!ok) ok = (mkdir(path, 0777 & ~user_umask) == 0);
- *p = '/';
- if (!ok) return 0;
- }
- return 1;
-}
-
-char *create_output_name(char *fname) {
- char *out, *p;
- if ((out = malloc(strlen(fname) + 1))) {
- /* remove leading slashes */
- while (*fname == '/' || *fname == '\\') fname++;
- /* if that removes all characters, just call it "x" */
- strcpy(out, (*fname) ? fname : "x");
-
- /* change "../" to "xx/" */
- for (p = out; *p; p++) {
- if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\\')) {
- p[0] = p[1] = 'x';
- }
- }
- }
- return out;
-}
-
-static int sortfunc(const void *a, const void *b) {
- off_t diff =
- ((* ((struct mschmd_file **) a))->offset) -
- ((* ((struct mschmd_file **) b))->offset);
- return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
-}
-
-int main(int argc, char *argv[]) {
- struct mschm_decompressor *chmd;
- struct mschmd_header *chm;
- struct mschmd_file *file, **f;
- unsigned int numf, i;
-
- setbuf(stdout, NULL);
- setbuf(stderr, NULL);
- user_umask = umask(0); umask(user_umask);
-
- MSPACK_SYS_SELFTEST(i);
- if (i) return 0;
-
- if ((chmd = mspack_create_chm_decompressor(NULL))) {
- for (argv++; *argv; argv++) {
- printf("%s\n", *argv);
- if ((chm = chmd->open(chmd, *argv))) {
-
- /* build an ordered list of files for maximum extraction speed */
- for (numf=0, file=chm->files; file; file = file->next) numf++;
- if ((f = (struct mschmd_file **) calloc(numf, sizeof(struct mschmd_file *)))) {
- for (i=0, file=chm->files; file; file = file->next) f[i++] = file;
- qsort(f, numf, sizeof(struct mschmd_file *), &sortfunc);
-
- for (i = 0; i < numf; i++) {
- char *outname = create_output_name(f[i]->filename);
- printf("Extracting %s\n", outname);
- ensure_filepath(outname);
- if (chmd->extract(chmd, f[i], outname)) {
- printf("%s: extract error on \"%s\": %s\n",
- *argv, f[i]->filename, ERROR(chmd));
- }
- free(outname);
- }
- free(f);
- }
- chmd->close(chmd, chm);
- }
- else {
- printf("%s: can't open -- %s\n", *argv, ERROR(chmd));
- }
- }
- mspack_destroy_chm_decompressor(chmd);
- }
- return 0;
-}
diff -Nru -w libmspack-0.8/src/error.h libmspack-0.10.1/src/error.h
--- libmspack-0.8/src/error.h 2017-08-13 20:35:30.000000000 +0200
+++ libmspack-0.10.1/src/error.h 1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-#define ERROR(base) error_msg(base->last_error(base))
-
-const char *error_msg(int error) {
- static char buf[32];
- switch (error) {
- case MSPACK_ERR_OK: return "no error";
- case MSPACK_ERR_ARGS: return "bad arguments to library function";
- case MSPACK_ERR_OPEN: return "error opening file";
- case MSPACK_ERR_READ: return "read error";
- case MSPACK_ERR_WRITE: return "write error";
- case MSPACK_ERR_SEEK: return "seek error";
- case MSPACK_ERR_NOMEMORY: return "out of memory";
- case MSPACK_ERR_SIGNATURE: return "bad signature";
- case MSPACK_ERR_DATAFORMAT: return "error in data format";
- case MSPACK_ERR_CHECKSUM: return "checksum error";
- case MSPACK_ERR_CRUNCH: return "compression error";
- case MSPACK_ERR_DECRUNCH: return "decompression error";
- }
-
- snprintf(buf, sizeof(buf), "unknown error %d", error);
- return buf;
-}
diff -Nru -w libmspack-0.8/src/msexpand.c libmspack-0.10.1/src/msexpand.c
--- libmspack-0.8/src/msexpand.c 2017-08-14 11:10:40.000000000 +0200
+++ libmspack-0.10.1/src/msexpand.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,48 +0,0 @@
-/* acts like Microsoft's EXPAND.EXE */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mspack.h>
-#include <error.h>
-
-int main(int argc, char *argv[]) {
- struct msszdd_decompressor *szddd;
- struct mskwaj_decompressor *kwajd;
- int err;
-
- if (argc != 3) {
- fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
- return 1;
- }
-
- /* exit if self-test reveals an error */
- MSPACK_SYS_SELFTEST(err);
- if (err) return 1;
-
- szddd = mspack_create_szdd_decompressor(NULL);
- kwajd = mspack_create_kwaj_decompressor(NULL);
-
- if (szddd && kwajd) {
- err = szddd->decompress(szddd, argv[1], argv[2]);
- /* if not SZDD file, try decompressing as KWAJ */
- if (err == MSPACK_ERR_SIGNATURE) {
- err = kwajd->decompress(kwajd, argv[1], argv[2]);
- }
- if (err != MSPACK_ERR_OK) {
- fprintf(stderr, "%s -> %s: %s\n", argv[1], argv[2], error_msg(err));
- }
- }
- else {
- fprintf(stderr, "can't create SZDD/KWAJ decompressor\n");
- err = 1;
- }
-
- mspack_destroy_szdd_decompressor(szddd);
- mspack_destroy_kwaj_decompressor(kwajd);
- return err ? 1 : 0;
-}
diff -Nru -w libmspack-0.8/src/oabextract.c libmspack-0.10.1/src/oabextract.c
--- libmspack-0.8/src/oabextract.c 2015-06-05 10:10:54.000000000 +0200
+++ libmspack-0.10.1/src/oabextract.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,41 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <mspack.h>
-
-#include <error.h>
-
-int main(int argc, char *argv[]) {
- struct msoab_decompressor *oabd;
- int err;
-
- setbuf(stdout, NULL);
- setbuf(stderr, NULL);
-
- MSPACK_SYS_SELFTEST(err);
- if (err) return 0;
-
- if ((oabd = mspack_create_oab_decompressor(NULL))) {
- if (argc == 3) {
- err = oabd->decompress(oabd, argv[1], argv[2]);
- if (err) fprintf(stderr, "%s -> %s: %s\n", argv[1], argv[2], error_msg(err));
- }
- else if (argc == 4) {
- err = oabd->decompress_incremental(oabd, argv[2], argv[1], argv[3]);
- if (err) fprintf(stderr, "%s + %s -> %s: %s\n", argv[1], argv[2], argv[3], error_msg(err));
- }
- else {
- fprintf(stderr, "Usage: %s <input> <output>\n", *argv);
- fprintf(stderr, " or %s <base> <patch> <output>\n", *argv);
- }
- mspack_destroy_oab_decompressor(oabd);
- }
- else {
- fprintf(stderr, "%s: can't make OAB decompressor\n", *argv);
- }
- return 0;
-}
diffstat for libmspack-0.9.1 libmspack-0.10.1
ChangeLog | 50 ++++
README | 2
config.h.in | 15 +
-configure | 245 +++++++++++++++++++++++-
configure.ac | 3
debian/changelog | 8
debian/copyright | 2
debian/libmspack-doc.docs | 4
mspack/cab.h | 2
mspack/cabd.c | 54 ++---
mspack/chmd.c | 27 +-
mspack/mspack.h | 31 ++-
mspack/oab.h | 1
mspack/oabd.c | 85 ++++----
mspack/system.c | 5
mspack/system.h | 19 -
-test/chminfo.c | 2
-test/test_files/chmd/short-system-filenames.chm |binary
18 files changed, 447 insertions(+), 108 deletions(-)
diff -Nru -w libmspack-0.9.1/ChangeLog libmspack-0.10.1/ChangeLog
--- libmspack-0.9.1/ChangeLog 2018-11-04 01:04:14.000000000 +0100
+++ libmspack-0.10.1/ChangeLog 2019-02-18 21:01:59.000000000 +0100
@@ -1,3 +1,53 @@
+2019-02-18 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * chmd_read_headers(): a CHM file name beginning "::" but shorter
+ than 33 bytes will lead to reading past the freshly-allocated name
+ buffer - checks for specific control filenames didn't take length
+ into account. Thanks to ADLab of Venustech for the report and
+ proof of concept.
+
+2019-02-18 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * chmd_read_headers(): CHM files can declare their chunks are any
+ size up to 4GB, and libmspack will attempt to allocate that to
+ read the file.
+
+ This is not a security issue; libmspack doesn't promise how much
+ memory it'll use to unpack files. You can set your own limits by
+ returning NULL in a custom mspack_system.alloc() implementation.
+
+ However, it would be good to validate chunk size further. With no
+ offical specification, only empirical data is available. All files
+ created by hhc.exe have a chunk size of 4096 bytes, and this is
+ matched by all the files I've found in the wild, except for one
+ which has a chunk size of 8192 bytes, which was created by someone
+ developing a CHM file creator 15 years ago, and they appear to
+ have abandoned it, so it seems 4096 is a de-facto standard.
+
+ I've changed the "chunk size is not a power of two" warning to
+ "chunk size is not 4096", and now only allow chunk sizes between
+ 22 and 8192 bytes. If you have CHM files with a larger chunk size,
+ please send them to me and I'll increase this upper limit.
+
+ Thanks to ADLab of Venustech for the report.
+
+2019-02-18 Stuart Caie <kyzer@cabextract.org.uk>
+
+ * oabd.c: replaced one-shot copying of uncompressed blocks (which
+ requires allocating a buffer of the size declared in the header,
+ which can be 4GB) with a fixed-size buffer. The buffer size is
+ user-controllable with the new msoab_decompressor::set_param()
+ method (check you have version 2 of the OAB decompressor), and
+ also controls the input buffer used for OAB's LZX decompression.
+
+ Reminder: compression formats can dictate how much memory is
+ needed to decompress them. If memory usage is a security concern
+ to you, write a custom mspack_system.alloc() that returns NULL
+ if "too much" memory is requested. Do not rely on libmspack adding
+ special heuristics to know not to request "too much".
+
+ Thanks to ADLab of Venustech for the report.
+
2018-11-03 Stuart Caie <kyzer@cabextract.org.uk>
* configure.ac, doc/Makefile.in, doc/Doxyfile.in: remove these
diff -Nru -w libmspack-0.9.1/config.h.in libmspack-0.10.1/config.h.in
--- libmspack-0.9.1/config.h.in 2018-11-06 12:17:02.000000000 +0100
+++ libmspack-0.10.1/config.h.in 2019-03-04 10:39:16.000000000 +0100
@@ -1,5 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
/* Turn debugging mode on? */
#undef DEBUG
@@ -81,6 +84,18 @@
/* Version number of package */
#undef VERSION
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
diff -Nru -w libmspack-0.9.1/configure libmspack-0.10.1/configure
diff -Nru -w libmspack-0.9.1/configure.ac libmspack-0.10.1/configure.ac
--- libmspack-0.9.1/configure.ac 2018-11-06 12:16:17.000000000 +0100
+++ libmspack-0.10.1/configure.ac 2019-03-04 10:36:51.000000000 +0100
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT([libmspack],[0.9.1alpha],[kyzer@cabextract.org.uk])
+AC_INIT([libmspack],[0.10.1alpha],[kyzer@cabextract.org.uk])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.11])
AM_SILENT_RULES([yes])
@@ -30,6 +30,7 @@
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
+AC_C_BIGENDIAN
AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
diff -Nru -w libmspack-0.9.1/debian/changelog libmspack-0.10.1/debian/changelog
--- libmspack-0.9.1/debian/changelog 2018-11-06 14:38:49.000000000 +0100
+++ libmspack-0.10.1/debian/changelog 2019-03-05 11:03:29.000000000 +0100
@@ -1,3 +1,11 @@
+libmspack (0.10.1-1) unstable; urgency=medium
+
+ * New upstream release:
+ + fix build on big-endian systems (Closes: #914794)
+ * Add missing JS files for documentation menu and search functions.
+
+ -- Marc Dequènes (Duck) <Duck@DuckCorp.org> Tue, 05 Mar 2019 19:03:29 +0900
+
libmspack (0.9.1-1) unstable; urgency=medium
* New upstream release:
diff -Nru -w libmspack-0.9.1/debian/copyright libmspack-0.10.1/debian/copyright
--- libmspack-0.9.1/debian/copyright 2018-07-29 06:03:32.000000000 +0200
+++ libmspack-0.10.1/debian/copyright 2019-03-05 07:24:35.000000000 +0100
@@ -2,6 +2,8 @@
Upstream-Name: libmspack
Upstream-Contact: Stuart Caie <kyzer@4u.net>
Source: https://www.cabextract.org.uk/libmspack/
+# doxygen-generated doc which is embedded in the upstream tarball; regenerated in the Debian build
+Files-excluded: doc/html
Files: *
diff -Nru -w libmspack-0.9.1/debian/libmspack-doc.docs libmspack-0.10.1/debian/libmspack-doc.docs
--- libmspack-0.9.1/debian/libmspack-doc.docs 2018-11-06 14:32:42.000000000 +0100
+++ libmspack-0.10.1/debian/libmspack-doc.docs 2019-03-05 10:52:56.000000000 +0100
@@ -1,4 +1,8 @@
doc/html/*.html
doc/html/*.css
doc/html/*.png
+# jquery.js is generated by doxygen
+# there is no easy way to replace it with a symlink to a system common version
+# rationale: /usr/share/doc/doxygen/README.jquery
+doc/html/*.js
doc/html/search
diff -Nru -w libmspack-0.9.1/mspack/cabd.c libmspack-0.10.1/mspack/cabd.c
--- libmspack-0.9.1/mspack/cabd.c 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/cabd.c 2019-03-04 02:09:26.000000000 +0100
@@ -156,10 +156,10 @@
self->d = NULL;
self->error = MSPACK_ERR_OK;
- self->param[MSCABD_PARAM_SEARCHBUF] = 32768;
- self->param[MSCABD_PARAM_FIXMSZIP] = 0;
- self->param[MSCABD_PARAM_DECOMPBUF] = 4096;
- self->param[MSCABD_PARAM_SALVAGE] = 0;
+ self->searchbuf_size = 32768;
+ self->fix_mszip = 0;
+ self->buf_size = 4096;
+ self->salvage = 0;
}
return (struct mscab_decompressor *) self;
}
@@ -203,7 +203,7 @@
if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
if ((cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
cab->base.filename = filename;
- error = cabd_read_headers(sys, fh, cab, (off_t) 0, self->param[MSCABD_PARAM_SALVAGE], 0);
+ error = cabd_read_headers(sys, fh, cab, (off_t) 0, self->salvage, 0);
if (error) {
cabd_close(base, (struct mscabd_cabinet *) cab);
cab = NULL;
@@ -600,7 +600,7 @@
sys = self->system;
/* allocate a search buffer */
- search_buf = (unsigned char *) sys->alloc(sys, (size_t) self->param[MSCABD_PARAM_SEARCHBUF]);
+ search_buf = (unsigned char *) sys->alloc(sys, (size_t) self->searchbuf_size);
if (!search_buf) {
self->error = MSPACK_ERR_NOMEMORY;
return NULL;
@@ -649,7 +649,7 @@
struct mspack_system *sys = self->system;
unsigned char *p, *pend, state = 0;
unsigned int cablen_u32 = 0, foffset_u32 = 0;
- int false_cabs = 0, salvage = self->param[MSCABD_PARAM_SALVAGE];
+ int false_cabs = 0;
#if !LARGEFILE_SUPPORT
/* detect 32-bit off_t overflow */
@@ -664,8 +664,8 @@
/* search length is either the full length of the search buffer, or the
* amount of data remaining to the end of the file, whichever is less. */
length = flen - offset;
- if (length > self->param[MSCABD_PARAM_SEARCHBUF]) {
- length = self->param[MSCABD_PARAM_SEARCHBUF];
+ if (length > self->searchbuf_size) {
+ length = self->searchbuf_size;
}
/* fill the search buffer with data from disk */
@@ -729,14 +729,14 @@
* mode, don't check the alleged length, allow it to be garbage */
if ((foffset_u32 < cablen_u32) &&
((caboff + (off_t) foffset_u32) < (flen + 32)) &&
- (((caboff + (off_t) cablen_u32) < (flen + 32)) || salvage))
+ (((caboff + (off_t) cablen_u32) < (flen + 32)) || self->salvage))
{
/* likely cabinet found -- try reading it */
if (!(cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
return MSPACK_ERR_NOMEMORY;
}
cab->base.filename = filename;
- if (cabd_read_headers(sys, fh, cab, caboff, salvage, 1)) {
+ if (cabd_read_headers(sys, fh, cab, caboff, self->salvage, 1)) {
/* destroy the failed cabinet */
cabd_close((struct mscab_decompressor *) self,
(struct mscabd_cabinet *) cab);
@@ -1030,7 +1030,7 @@
*/
filelen = file->length;
if (filelen > CAB_LENGTHMAX || (file->offset + filelen) > CAB_LENGTHMAX) {
- if (self->param[MSCABD_PARAM_SALVAGE]) {
+ if (self->salvage) {
filelen = CAB_LENGTHMAX - file->offset;
}
else {
@@ -1048,7 +1048,7 @@
/* if file goes beyond what can be decoded, given an error.
* In salvage mode, don't assume block sizes, just try decoding
*/
- if (!self->param[MSCABD_PARAM_SALVAGE]) {
+ if (!self->salvage) {
off_t maxlen = fol->base.num_blocks * CAB_BLOCKMAX;
if ((file->offset + filelen) > maxlen) {
sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
@@ -1165,24 +1165,22 @@
switch (ct & cffoldCOMPTYPE_MASK) {
case cffoldCOMPTYPE_NONE:
self->d->decompress = (int (*)(void *, off_t)) &noned_decompress;
- self->d->state = noned_init(&self->d->sys, fh, fh,
- self->param[MSCABD_PARAM_DECOMPBUF]);
+ self->d->state = noned_init(&self->d->sys, fh, fh, self->buf_size);
break;
case cffoldCOMPTYPE_MSZIP:
self->d->decompress = (int (*)(void *, off_t)) &mszipd_decompress;
- self->d->state = mszipd_init(&self->d->sys, fh, fh,
- self->param[MSCABD_PARAM_DECOMPBUF],
- self->param[MSCABD_PARAM_FIXMSZIP]);
+ self->d->state = mszipd_init(&self->d->sys, fh, fh, self->buf_size,
+ self->fix_mszip);
break;
case cffoldCOMPTYPE_QUANTUM:
self->d->decompress = (int (*)(void *, off_t)) &qtmd_decompress;
self->d->state = qtmd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f,
- self->param[MSCABD_PARAM_DECOMPBUF]);
+ self->buf_size);
break;
case cffoldCOMPTYPE_LZX:
self->d->decompress = (int (*)(void *, off_t)) &lzxd_decompress;
self->d->state = lzxd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f, 0,
- self->param[MSCABD_PARAM_DECOMPBUF], (off_t)0,0);
+ self->buf_size, (off_t)0,0);
break;
default:
return self->error = MSPACK_ERR_DATAFORMAT;
@@ -1221,10 +1219,10 @@
struct mspack_system *sys = self->system;
int avail, todo, outlen, ignore_cksum, ignore_blocksize;
- ignore_cksum = self->param[MSCABD_PARAM_SALVAGE] ||
- (self->param[MSCABD_PARAM_FIXMSZIP] &&
+ ignore_cksum = self->salvage ||
+ (self->fix_mszip &&
((self->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP));
- ignore_blocksize = self->param[MSCABD_PARAM_SALVAGE];
+ ignore_blocksize = self->salvage;
todo = bytes;
while (todo > 0) {
@@ -1244,7 +1242,7 @@
/* check if we're out of input blocks, advance block counter */
if (self->d->block++ >= self->d->folder->base.num_blocks) {
- if (!self->param[MSCABD_PARAM_SALVAGE]) {
+ if (!self->salvage) {
self->read_error = MSPACK_ERR_DATAFORMAT;
}
else {
@@ -1481,17 +1479,17 @@
switch (param) {
case MSCABD_PARAM_SEARCHBUF:
if (value < 4) return MSPACK_ERR_ARGS;
- self->param[MSCABD_PARAM_SEARCHBUF] = value;
+ self->searchbuf_size = value;
break;
case MSCABD_PARAM_FIXMSZIP:
- self->param[MSCABD_PARAM_FIXMSZIP] = value;
+ self->fix_mszip = value;
break;
case MSCABD_PARAM_DECOMPBUF:
if (value < 4) return MSPACK_ERR_ARGS;
- self->param[MSCABD_PARAM_DECOMPBUF] = value;
+ self->buf_size = value;
break;
case MSCABD_PARAM_SALVAGE:
- self->param[MSCABD_PARAM_SALVAGE] = value;
+ self->salvage = value;
break;
default:
return MSPACK_ERR_ARGS;
diff -Nru -w libmspack-0.9.1/mspack/cab.h libmspack-0.10.1/mspack/cab.h
--- libmspack-0.9.1/mspack/cab.h 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/cab.h 2019-03-04 10:09:35.000000000 +0100
@@ -113,7 +113,7 @@
struct mscab_decompressor base;
struct mscabd_decompress_state *d;
struct mspack_system *system;
- int param[4]; /* !!! MATCH THIS TO NUM OF PARAMS IN MSPACK.H !!! */
+ int buf_size, searchbuf_size, fix_mszip, salvage; /* params */
int error, read_error;
};
diff -Nru -w libmspack-0.9.1/mspack/chmd.c libmspack-0.10.1/mspack/chmd.c
--- libmspack-0.9.1/mspack/chmd.c 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/chmd.c 2019-03-04 02:10:28.000000000 +0100
@@ -44,7 +44,7 @@
struct mschm_decompressor_p *self, struct mschmd_file *file);
static int read_reset_table(
struct mschm_decompressor_p *self, struct mschmd_sec_mscompressed *sec,
- int entry, off_t *length_ptr, off_t *offset_ptr);
+ unsigned int entry, off_t *length_ptr, off_t *offset_ptr);
static int read_spaninfo(
struct mschm_decompressor_p *self, struct mschmd_sec_mscompressed *sec,
off_t *length_ptr);
@@ -381,14 +381,18 @@
D(("more than 100,000 chunks"))
return MSPACK_ERR_DATAFORMAT;
}
+ if (chm->chunk_size > 8192) {
+ D(("chunk size over 8192 (get in touch if this is valid)"))
+ return MSPACK_ERR_DATAFORMAT;
+ }
if ((off_t)chm->chunk_size * (off_t)chm->num_chunks > chm->length) {
D(("chunks larger than entire file"))
return MSPACK_ERR_DATAFORMAT;
}
/* common sense checks on header section 1 fields */
- if ((chm->chunk_size & (chm->chunk_size - 1)) != 0) {
- sys->message(fh, "WARNING; chunk size is not a power of two");
+ if (chm->chunk_size != 4096) {
+ sys->message(fh, "WARNING; chunk size is not 4096");
}
if (chm->first_pmgl != 0) {
sys->message(fh, "WARNING; first PMGL chunk is not zero");
@@ -435,7 +439,7 @@
sys->message(fh, "WARNING; PMGL quickref area is too small");
}
if (EndGetI32(&chunk[pmgl_QuickRefSize]) >
- ((int)chm->chunk_size - pmgl_Entries))
+ (chm->chunk_size - pmgl_Entries))
{
sys->message(fh, "WARNING; PMGL quickref area is too large");
}
@@ -483,20 +487,18 @@
if (name[0] == ':' && name[1] == ':') {
/* system file */
- if (memcmp(&name[2], &content_name[2], 31L) == 0) {
- if (memcmp(&name[33], &content_name[33], 8L) == 0) {
+ if (name_len == 40 && memcmp(name, content_name, 40) == 0) {
chm->sec1.content = fi;
}
- else if (memcmp(&name[33], &control_name[33], 11L) == 0) {
+ else if (name_len == 44 && memcmp(name, control_name, 44) == 0) {
chm->sec1.control = fi;
}
- else if (memcmp(&name[33], &spaninfo_name[33], 8L) == 0) {
+ else if (name_len == 41 && memcmp(name, spaninfo_name, 41) == 0) {
chm->sec1.spaninfo = fi;
}
- else if (memcmp(&name[33], &rtable_name[33], 72L) == 0) {
+ else if (name_len == 105 && memcmp(name, rtable_name, 105) == 0) {
chm->sec1.rtable = fi;
}
- }
fi->next = chm->sysfiles;
chm->sysfiles = fi;
}
@@ -589,7 +591,7 @@
}
/* stop simple infinite loops: can't visit the same chunk twice */
- if ((int)n == EndGetI32(&chunk[pmgl_NextChunk])) {
+ if (n == EndGetI32(&chunk[pmgl_NextChunk])) {
break;
}
}
@@ -1154,7 +1156,8 @@
*/
static int read_reset_table(struct mschm_decompressor_p *self,
struct mschmd_sec_mscompressed *sec,
- int entry, off_t *length_ptr, off_t *offset_ptr)
+ unsigned int entry,
+ off_t *length_ptr, off_t *offset_ptr)
{
struct mspack_system *sys = self->system;
unsigned char *data;
diff -Nru -w libmspack-0.9.1/mspack/mspack.h libmspack-0.10.1/mspack/mspack.h
--- libmspack-0.9.1/mspack/mspack.h 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/mspack.h 2019-02-18 21:25:16.000000000 +0100
@@ -1,5 +1,5 @@
/* libmspack -- a library for working with Microsoft compression formats.
- * (C) 2003-2016 Stuart Caie <kyzer@cabextract.org.uk>
+ * (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
@@ -1554,7 +1554,7 @@
*/
int (*set_param)(struct mschm_compressor *self,
int param,
- unsigned int value);
+ int value);
/**
* Returns the error code set by the most recently called method.
@@ -1853,7 +1853,7 @@
*/
int (*set_param)(struct msszdd_compressor *self,
int param,
- unsigned int value);
+ int value);
/**
* Returns the error code set by the most recently called method.
@@ -2091,7 +2091,7 @@
*/
int (*set_param)(struct mskwaj_compressor *self,
int param,
- unsigned int value);
+ int value);
/**
@@ -2353,8 +2353,31 @@
const char *input,
const char *base,
const char *output);
+
+ /**
+ * Sets an OAB decompression engine parameter. Available only in OAB
+ * decompressor version 2 and above.
+ *
+ * - #MSOABD_PARAM_DECOMPBUF: How many bytes should be used as an input
+ * buffer by decompressors? The minimum value is 16. The default value
+ * is 4096.
+ *
+ * @param self a self-referential pointer to the msoab_decompressor
+ * instance being called
+ * @param param the parameter to set
+ * @param value the value to set the parameter to
+ * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
+ * is a problem with either parameter or value.
+ */
+ int (*set_param)(struct msoab_decompressor *self,
+ int param,
+ int value);
+
};
+/** msoab_decompressor::set_param() parameter: size of decompression buffer */
+#define MSOABD_PARAM_DECOMPBUF (0)
+
#ifdef __cplusplus
}
#endif
diff -Nru -w libmspack-0.9.1/mspack/oabd.c libmspack-0.10.1/mspack/oabd.c
--- libmspack-0.9.1/mspack/oabd.c 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/oabd.c 2019-03-04 10:11:49.000000000 +0100
@@ -33,6 +33,11 @@
static int oabd_decompress_incremental(struct msoab_decompressor *self,
const char *input, const char *base,
const char *output);
+static int oabd_param(struct msoab_decompressor *base, int param, int value);
+static int copy_fh(struct mspack_system *sys, struct mspack_file *infh,
+ struct mspack_file *outfh, size_t bytes_to_copy,
+ unsigned char *buf, int buf_size);
+
struct msoab_decompressor *
mspack_create_oab_decompressor(struct mspack_system *sys)
@@ -45,7 +50,9 @@
if ((self = (struct msoab_decompressor_p *) sys->alloc(sys, sizeof(struct msoab_decompressor_p)))) {
self->base.decompress = &oabd_decompress;
self->base.decompress_incremental = &oabd_decompress_incremental;
+ self->base.set_param = &oabd_param;
self->system = sys;
+ self->buf_size = 4096;
}
return (struct msoab_decompressor *) self;
}
@@ -132,17 +139,13 @@
block_max = EndGetI32(&hdrbuf[oabhead_BlockMax]);
target_size = EndGetI32(&hdrbuf[oabhead_TargetSize]);
- /* We use it for reading block headers too */
- if (block_max < oabblk_SIZEOF)
- block_max = oabblk_SIZEOF;
-
outfh = sys->open(sys, output, MSPACK_SYS_OPEN_WRITE);
if (!outfh) {
ret = MSPACK_ERR_OPEN;
goto out;
}
- buf = sys->alloc(sys, block_max);
+ buf = sys->alloc(sys, self->buf_size);
if (!buf) {
ret = MSPACK_ERR_NOMEMORY;
goto out;
@@ -181,14 +184,8 @@
ret = MSPACK_ERR_DATAFORMAT;
goto out;
}
- if (sys->read(infh, buf, blk_dsize) != (int)blk_dsize) {
- ret = MSPACK_ERR_READ;
- goto out;
- }
- if (sys->write(outfh, buf, blk_dsize) != (int)blk_dsize) {
- ret = MSPACK_ERR_WRITE;
- goto out;
- }
+ ret = copy_fh(sys, infh, outfh, blk_dsize, buf, self->buf_size);
+ if (ret) goto out;
} else {
/* LZX compressed block */
window_bits = 17;
@@ -200,7 +197,7 @@
out_ofh.crc = 0xffffffff;
lzx = lzxd_init(&oabd_sys, (void *)&in_ofh, (void *)&out_ofh, window_bits,
- 0, 4096, blk_dsize, 1);
+ 0, self->buf_size, blk_dsize, 1);
if (!lzx) {
ret = MSPACK_ERR_NOMEMORY;
goto out;
@@ -214,18 +211,8 @@
lzx = NULL;
/* Consume any trailing padding bytes before the next block */
- while (in_ofh.available) {
- int count = block_max;
- if ((size_t)count > in_ofh.available)
- count = in_ofh.available;
-
- count = sys->read(infh, buf, count);
- if (count < 0) {
- ret = MSPACK_ERR_READ;
- goto out;
- }
- in_ofh.available -= count;
- }
+ ret = copy_fh(sys, infh, NULL, in_ofh.available, buf, self->buf_size);
+ if (ret) goto out;
if (out_ofh.crc != blk_crc) {
ret = MSPACK_ERR_CHECKSUM;
@@ -301,7 +288,7 @@
goto out;
}
- buf = sys->alloc(sys, block_max);
+ buf = sys->alloc(sys, self->buf_size);
if (!buf) {
ret = MSPACK_ERR_NOMEMORY;
goto out;
@@ -364,18 +351,8 @@
lzx = NULL;
/* Consume any trailing padding bytes before the next block */
- while (in_ofh.available) {
- int count = block_max;
- if ((size_t)count > in_ofh.available)
- count = in_ofh.available;
-
- count = sys->read(infh, buf, count);
- if (count < 0) {
- ret = MSPACK_ERR_READ;
- goto out;
- }
- in_ofh.available -= count;
- }
+ ret = copy_fh(sys, infh, NULL, in_ofh.available, buf, self->buf_size);
+ if (ret) goto out;
if (out_ofh.crc != blk_crc) {
ret = MSPACK_ERR_CHECKSUM;
@@ -394,3 +371,33 @@
return ret;
}
+
+static int copy_fh(struct mspack_system *sys, struct mspack_file *infh,
+ struct mspack_file *outfh, size_t bytes_to_copy,
+ unsigned char *buf, int buf_size)
+{
+ while (bytes_to_copy) {
+ int run = buf_size;
+ if ((size_t) run > bytes_to_copy) {
+ run = (int) bytes_to_copy;
+ }
+ if (sys->read(infh, buf, run) != run) {
+ return MSPACK_ERR_READ;
+ }
+ if (outfh && sys->write(outfh, buf, run) != run) {
+ return MSPACK_ERR_WRITE;
+ }
+ bytes_to_copy -= run;
+ }
+ return MSPACK_ERR_OK;
+}
+
+static int oabd_param(struct msoab_decompressor *base, int param, int value) {
+ struct msoab_decompressor_p *self = (struct msoab_decompressor_p *) base;
+ if (self && param == MSOABD_PARAM_DECOMPBUF && value >= 16) {
+ /* must be at least 16 bytes (patchblk_SIZEOF, oabblk_SIZEOF) */
+ self->buf_size = value;
+ return MSPACK_ERR_OK;
+ }
+ return MSPACK_ERR_ARGS;
+}
diff -Nru -w libmspack-0.9.1/mspack/oab.h libmspack-0.10.1/mspack/oab.h
--- libmspack-0.9.1/mspack/oab.h 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/oab.h 2019-02-18 17:39:40.000000000 +0100
@@ -27,6 +27,7 @@
struct msoab_decompressor_p {
struct msoab_decompressor base;
struct mspack_system *system;
+ int buf_size;
/* todo */
};
diff -Nru -w libmspack-0.9.1/mspack/system.c libmspack-0.10.1/mspack/system.c
--- libmspack-0.9.1/mspack/system.c 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/system.c 2019-02-18 17:26:17.000000000 +0100
@@ -31,12 +31,15 @@
* - added MSCABD_PARAM_SALVAGE
*/
case MSPACK_VER_MSCABD:
+ /* OAB decoder version 1 -> 2 changes:
+ * - added msoab_decompressor::set_param and MSOABD_PARAM_DECOMPBUF
+ */
+ case MSPACK_VER_MSOABD:
return 2;
case MSPACK_VER_LIBRARY:
case MSPACK_VER_SYSTEM:
case MSPACK_VER_MSSZDDD:
case MSPACK_VER_MSKWAJD:
- case MSPACK_VER_MSOABD:
return 1;
case MSPACK_VER_MSCABC:
case MSPACK_VER_MSCHMC:
diff -Nru -w libmspack-0.9.1/mspack/system.h libmspack-0.10.1/mspack/system.h
--- libmspack-0.9.1/mspack/system.h 2018-11-05 12:53:09.000000000 +0100
+++ libmspack-0.10.1/mspack/system.h 2019-03-04 02:10:28.000000000 +0100
@@ -81,20 +81,19 @@
#endif
/* endian-neutral reading of little-endian data */
-#define __egi32(a,n) ( ((((unsigned char *) a)[n+3]) << 24) | \
- ((((unsigned char *) a)[n+2]) << 16) | \
- ((((unsigned char *) a)[n+1]) << 8) | \
- ((((unsigned char *) a)[n+0])))
-#define EndGetI64(a) ((((unsigned long long int) __egi32(a,4)) << 32) | \
- ((unsigned int) __egi32(a,0)))
+#define __egi32(a,n) (((unsigned int) ((unsigned char *)(a))[n+3] << 24) | \
+ ((unsigned int) ((unsigned char *)(a))[n+2] << 16) | \
+ ((unsigned int) ((unsigned char *)(a))[n+1] << 8) | \
+ ((unsigned int) ((unsigned char *)(a))[n]))
+#define EndGetI64(a) (((unsigned long long int) __egi32(a,4) << 32) | __egi32(a,0))
#define EndGetI32(a) __egi32(a,0)
#define EndGetI16(a) ((((a)[1])<<8)|((a)[0]))
/* endian-neutral reading of big-endian data */
-#define EndGetM32(a) (((((unsigned char *) a)[0]) << 24) | \
- ((((unsigned char *) a)[1]) << 16) | \
- ((((unsigned char *) a)[2]) << 8) | \
- ((((unsigned char *) a)[3])))
+#define EndGetM32(a) (((unsigned int) ((unsigned char *)(a))[0] << 24) | \
+ ((unsigned int) ((unsigned char *)(a))[1] << 16) | \
+ ((unsigned int) ((unsigned char *)(a))[2] << 8) | \
+ ((unsigned int) ((unsigned char *)(a))[3]))
#define EndGetM16(a) ((((a)[0])<<8)|((a)[1]))
extern struct mspack_system *mspack_default_system;
diff -Nru -w libmspack-0.9.1/README libmspack-0.10.1/README
--- libmspack-0.9.1/README 2018-11-06 12:16:32.000000000 +0100
+++ libmspack-0.10.1/README 2019-03-04 10:36:57.000000000 +0100
@@ -1,4 +1,4 @@
-libmspack 0.9.1alpha
+libmspack 0.10.1alpha
The purpose of libmspack is to provide compressors and decompressors,
archivers and dearchivers for Microsoft compression formats: CAB, CHM, WIM,
Reply to: