diff -Nru libmspack-0.9.1/ChangeLog libmspack-0.10.1/ChangeLog --- libmspack-0.9.1/ChangeLog 2018-11-04 00:04:14.000000000 +0000 +++ libmspack-0.10.1/ChangeLog 2019-02-18 20:01:59.000000000 +0000 @@ -1,3 +1,53 @@ +2019-02-18 Stuart Caie + + * 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 + + * 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 + + * 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 * configure.ac, doc/Makefile.in, doc/Doxyfile.in: remove these diff -Nru libmspack-0.9.1/config.h.in libmspack-0.10.1/config.h.in --- libmspack-0.9.1/config.h.in 2018-11-06 11:17:02.000000000 +0000 +++ libmspack-0.10.1/config.h.in 2019-03-04 09:39:16.000000000 +0000 @@ -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 libmspack-0.9.1/configure libmspack-0.10.1/configure --- libmspack-0.9.1/configure 2018-11-06 11:16:55.000000000 +0000 +++ libmspack-0.10.1/configure 2019-03-04 09:39:16.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libmspack 0.9.1alpha. +# Generated by GNU Autoconf 2.69 for libmspack 0.10.1alpha. # # Report bugs to . # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='libmspack' PACKAGE_TARNAME='libmspack' -PACKAGE_VERSION='0.9.1alpha' -PACKAGE_STRING='libmspack 0.9.1alpha' +PACKAGE_VERSION='0.10.1alpha' +PACKAGE_STRING='libmspack 0.10.1alpha' PACKAGE_BUGREPORT='kyzer@cabextract.org.uk' PACKAGE_URL='' @@ -1328,7 +1328,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libmspack 0.9.1alpha to adapt to many kinds of systems. +\`configure' configures libmspack 0.10.1alpha to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1399,7 +1399,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libmspack 0.9.1alpha:";; + short | recursive ) echo "Configuration of libmspack 0.10.1alpha:";; esac cat <<\_ACEOF @@ -1511,7 +1511,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libmspack configure 0.9.1alpha +libmspack configure 0.10.1alpha generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2117,7 +2117,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libmspack $as_me 0.9.1alpha, which was +It was created by libmspack $as_me 0.10.1alpha, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2981,7 +2981,7 @@ # Define the identity of the package. PACKAGE='libmspack' - VERSION='0.9.1alpha' + VERSION='0.10.1alpha' cat >>confdefs.h <<_ACEOF @@ -12575,6 +12575,230 @@ ;; esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = xyes; then : @@ -13113,6 +13337,7 @@ Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi + : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files @@ -13509,7 +13734,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libmspack $as_me 0.9.1alpha, which was +This file was extended by libmspack $as_me 0.10.1alpha, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13575,7 +13800,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libmspack config.status 0.9.1alpha +libmspack config.status 0.10.1alpha configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru libmspack-0.9.1/configure.ac libmspack-0.10.1/configure.ac --- libmspack-0.9.1/configure.ac 2018-11-06 11:16:17.000000000 +0000 +++ libmspack-0.10.1/configure.ac 2019-03-04 09:36:51.000000000 +0000 @@ -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 libmspack-0.9.1/debian/changelog libmspack-0.10.1/debian/changelog --- libmspack-0.9.1/debian/changelog 2019-01-07 17:17:28.000000000 +0000 +++ libmspack-0.10.1/debian/changelog 2019-03-05 10:03:29.000000000 +0000 @@ -1,9 +1,10 @@ -libmspack (0.9.1-1ubuntu1) disco; urgency=medium +libmspack (0.10.1-1) unstable; urgency=medium - * d/p/big-endian-md5-fix.patch: fix md5 on big endian. Thanks to - Stuart Caie . (LP: #1810817) (Closes: #914794) + * New upstream release: + + fix build on big-endian systems (Closes: #914794) + * Add missing JS files for documentation menu and search functions. - -- Andreas Hasenack Mon, 07 Jan 2019 15:17:28 -0200 + -- Marc Dequènes (Duck) Tue, 05 Mar 2019 19:03:29 +0900 libmspack (0.9.1-1) unstable; urgency=medium diff -Nru libmspack-0.9.1/debian/control libmspack-0.10.1/debian/control --- libmspack-0.9.1/debian/control 2019-01-07 17:17:28.000000000 +0000 +++ libmspack-0.10.1/debian/control 2019-03-05 06:24:16.000000000 +0000 @@ -1,8 +1,7 @@ Source: libmspack Section: libs Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Marc Dequènes (Duck) +Maintainer: Marc Dequènes (Duck) Standards-Version: 4.2.1 Build-Depends: dpkg-dev (>= 1.16.1.1), debhelper (>= 11) Build-Depends-indep: doxygen, graphviz diff -Nru libmspack-0.9.1/debian/copyright libmspack-0.10.1/debian/copyright --- libmspack-0.9.1/debian/copyright 2019-01-07 17:17:28.000000000 +0000 +++ libmspack-0.10.1/debian/copyright 2019-03-05 06:24:35.000000000 +0000 @@ -2,6 +2,8 @@ Upstream-Name: libmspack Upstream-Contact: Stuart Caie 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 libmspack-0.9.1/debian/libmspack-doc.docs libmspack-0.10.1/debian/libmspack-doc.docs --- libmspack-0.9.1/debian/libmspack-doc.docs 2019-01-07 17:17:28.000000000 +0000 +++ libmspack-0.10.1/debian/libmspack-doc.docs 2019-03-05 09:52:56.000000000 +0000 @@ -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 libmspack-0.9.1/debian/patches/big-endian-md5-fix.patch libmspack-0.10.1/debian/patches/big-endian-md5-fix.patch --- libmspack-0.9.1/debian/patches/big-endian-md5-fix.patch 2019-01-07 17:17:28.000000000 +0000 +++ libmspack-0.10.1/debian/patches/big-endian-md5-fix.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -Description: fix md5 on big endian - Add AC_C_BIGENDIAN so md5.c works on big-endian systems without manually - setting WORDS_BIGENDIAN - . - Backport note: the upstream git repo hosts both cabextract and libmspack, - and the commit referenced below in the "Origin" header fixes both. -Author: Stuart Caie -Origin: upstream, https://github.com/kyz/libmspack/commit/c19e707936947b45cf05bc9aaee68517c6c2aca6 -Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914794 -Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libmspack/+bug/1810817 -Last-Update: 2019-01-07 ---- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ ---- a/configure.ac -+++ b/configure.ac -@@ -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 libmspack-0.9.1/debian/patches/series libmspack-0.10.1/debian/patches/series --- libmspack-0.9.1/debian/patches/series 2019-01-07 17:17:28.000000000 +0000 +++ libmspack-0.10.1/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -big-endian-md5-fix.patch diff -Nru libmspack-0.9.1/mspack/cabd.c libmspack-0.10.1/mspack/cabd.c --- libmspack-0.9.1/mspack/cabd.c 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/cabd.c 2019-03-04 01:09:26.000000000 +0000 @@ -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 libmspack-0.9.1/mspack/cab.h libmspack-0.10.1/mspack/cab.h --- libmspack-0.9.1/mspack/cab.h 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/cab.h 2019-03-04 09:09:35.000000000 +0000 @@ -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 libmspack-0.9.1/mspack/chmd.c libmspack-0.10.1/mspack/chmd.c --- libmspack-0.9.1/mspack/chmd.c 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/chmd.c 2019-03-04 01:10:28.000000000 +0000 @@ -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); @@ -380,15 +380,19 @@ if (chm->num_chunks > 100000) { 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,19 +487,17 @@ 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) { - chm->sec1.content = fi; - } - else if (memcmp(&name[33], &control_name[33], 11L) == 0) { - chm->sec1.control = fi; - } - else if (memcmp(&name[33], &spaninfo_name[33], 8L) == 0) { - chm->sec1.spaninfo = fi; - } - else if (memcmp(&name[33], &rtable_name[33], 72L) == 0) { - chm->sec1.rtable = fi; - } + if (name_len == 40 && memcmp(name, content_name, 40) == 0) { + chm->sec1.content = fi; + } + else if (name_len == 44 && memcmp(name, control_name, 44) == 0) { + chm->sec1.control = fi; + } + else if (name_len == 41 && memcmp(name, spaninfo_name, 41) == 0) { + chm->sec1.spaninfo = fi; + } + 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 libmspack-0.9.1/mspack/mspack.h libmspack-0.10.1/mspack/mspack.h --- libmspack-0.9.1/mspack/mspack.h 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/mspack.h 2019-02-18 20:25:16.000000000 +0000 @@ -1,5 +1,5 @@ /* libmspack -- a library for working with Microsoft compression formats. - * (C) 2003-2016 Stuart Caie + * (C) 2003-2019 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 @@ -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 libmspack-0.9.1/mspack/oabd.c libmspack-0.10.1/mspack/oabd.c --- libmspack-0.9.1/mspack/oabd.c 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/oabd.c 2019-03-04 09:11:49.000000000 +0000 @@ -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 libmspack-0.9.1/mspack/oab.h libmspack-0.10.1/mspack/oab.h --- libmspack-0.9.1/mspack/oab.h 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/oab.h 2019-02-18 16:39:40.000000000 +0000 @@ -27,6 +27,7 @@ struct msoab_decompressor_p { struct msoab_decompressor base; struct mspack_system *system; + int buf_size; /* todo */ }; diff -Nru libmspack-0.9.1/mspack/system.c libmspack-0.10.1/mspack/system.c --- libmspack-0.9.1/mspack/system.c 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/system.c 2019-02-18 16:26:17.000000000 +0000 @@ -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 libmspack-0.9.1/mspack/system.h libmspack-0.10.1/mspack/system.h --- libmspack-0.9.1/mspack/system.h 2018-11-05 11:53:09.000000000 +0000 +++ libmspack-0.10.1/mspack/system.h 2019-03-04 01:10:28.000000000 +0000 @@ -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 libmspack-0.9.1/README libmspack-0.10.1/README --- libmspack-0.9.1/README 2018-11-06 11:16:32.000000000 +0000 +++ libmspack-0.10.1/README 2019-03-04 09:36:57.000000000 +0000 @@ -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, diff -Nru libmspack-0.9.1/test/chminfo.c libmspack-0.10.1/test/chminfo.c --- libmspack-0.9.1/test/chminfo.c 2018-11-06 11:27:31.000000000 +0000 +++ libmspack-0.10.1/test/chminfo.c 2019-03-04 09:33:36.000000000 +0000 @@ -53,12 +53,12 @@ return result; } -#define READ_ENCINT(var, label) do { \ - (var) = 0; \ +#define READ_ENCINT(var, label) do { \ + (var) = 0; \ do { \ - if (p > &chunk[chm->chunk_size-2]) goto label; \ - (var) = ((var) << 7) | (*p & 0x7F); \ - } while (*p++ & 0x80); \ + if (p > &chunk[chm->chunk_size-2]) goto label; \ + (var) = ((var) << 7) | (*p & 0x7F); \ + } while (*p++ & 0x80); \ } while (0) void print_dir(struct mschmd_header *chm, char *filename) { @@ -201,7 +201,7 @@ if ((chm = chmd->open(chmd, *argv))) { printf(" chmhead_Version %u\n", chm->version); printf(" chmhead_Timestamp %u\n", chm->timestamp); - printf(" chmhead_LanguageID %u\n", chm->language); + printf(" chmhead_LanguageID %u\n", chm->language); printf(" chmhs0_FileLen %" LD "\n", chm->length); printf(" chmhst_OffsetHS1 %" LD "\n", chm->dir_offset); printf(" chmhst3_OffsetCS0 %" LD "\n", chm->sec0.offset); @@ -252,7 +252,7 @@ case 4: for (i = 0; i < numf && pos < len; i++, pos += 4) { unsigned int rtdata = EndGetI32(&data[pos]); - printf(" %-10u -> %-10u [ %llu %u ]\n", + printf(" %-10u -> %-10u [ %" LU " %u ]\n", i * EndGetI32(&data[32]), rtdata, contents + rtdata, Binary files /tmp/tmpXcCCEf/z0O_AFN93z/libmspack-0.9.1/test/test_files/chmd/short-system-filenames.chm and /tmp/tmpXcCCEf/0DeMyB4mD9/libmspack-0.10.1/test/test_files/chmd/short-system-filenames.chm differ