Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libaec for openSUSE:Factory checked in at 2026-11-06 19:35:35 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libaec (Old) and /work/SRC/openSUSE:Factory/.libaec.new.3759290 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libaec" Fri Nov 6 19:35:35 2026 rev:13 rq:1395138 version:1.1.8 Changes: -------- --- /work/SRC/openSUSE:Factory/libaec/libaec.changes 2026-05-23 23:27:26.532870968 +0200 +++ /work/SRC/openSUSE:Factory/.libaec.new.3759290/libaec.changes 2026-11-06 19:39:07.313830141 +0100 @@ -1,0 +2,19 @@ +Wed Nov 4 15:24:30 UTC 2026 - Manfred Schwarb <[email protected]> + +- Update to version 1.1.8: + * The CMake package reports the installed library flavors as + components "shared" and "static", e.g. + find_package(libaec CONFIG REQUIRED COMPONENTS static) + * After AEC_DATA_ERROR, further calls to aec_decode() on the same + stream keep returning AEC_DATA_ERROR + * Heap buffer overflow in SZ_BufftoBuffCompress with negative + parameters + * Heap buffer overflow when decoding resumed after AEC_DATA_ERROR. + * Uninitialized memory returned by aec_decode_range and + SZ_BufftoBuffDecompress for truncated input + * Out-of-bounds read in the decoder for fundamental sequences of 2^31 + or more zero bits (boo#1289203; CVE-2026-120457) + * Corrupted split blocks decoded to garbage instead of returning + AEC_DATA_ERROR + +------------------------------------------------------------------- Old: ---- libaec-v1.1.7.tar.gz New: ---- libaec-v1.1.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libaec.spec ++++++ --- /var/tmp/diff_new_pack.QqYuhd/_old 2026-11-06 19:39:08.269870131 +0100 +++ /var/tmp/diff_new_pack.QqYuhd/_new 2026-11-06 19:39:08.272870256 +0100 @@ -17,7 +17,7 @@ Name: libaec -Version: 1.1.7 +Version: 1.1.8 Release: 0 Summary: Adaptive Entropy Coding library License: BSD-2-Clause @@ -109,7 +109,6 @@ %files -n libsz2 %license LICENSE.txt -%doc doc/README.SZIP %{_libdir}/libsz.so.2* %files -n sz2-devel ++++++ libaec-v1.1.7.tar.gz -> libaec-v1.1.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/.github/workflows/cmake-multi-platform.yml new/libaec-v1.1.8/.github/workflows/cmake-multi-platform.yml --- old/libaec-v1.1.7/.github/workflows/cmake-multi-platform.yml 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/.github/workflows/cmake-multi-platform.yml 2026-11-04 15:51:40.000000000 +0100 @@ -41,6 +41,8 @@ - os: ubuntu-latest c_compiler: cl - os: macos-latest + c_compiler: gcc + - os: macos-latest c_compiler: cl steps: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/CHANGELOG.md new/libaec-v1.1.8/CHANGELOG.md --- old/libaec-v1.1.7/CHANGELOG.md 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/CHANGELOG.md 2026-11-04 15:51:40.000000000 +0100 @@ -1,6 +1,28 @@ # libaec Changelog All notable changes to libaec will be documented in this file. +## [1.1.8] - 2026-11-04 + +### Added +- The CMake package reports the installed library flavors as + components "shared" and "static", e.g. + find_package(libaec CONFIG REQUIRED COMPONENTS static). + +### Changed +- After AEC_DATA_ERROR, further calls to aec_decode() on the same + stream keep returning AEC_DATA_ERROR. + +### Fixed +- Heap buffer overflow in SZ_BufftoBuffCompress with negative + parameters. +- Heap buffer overflow when decoding resumed after AEC_DATA_ERROR. +- Uninitialized memory returned by aec_decode_range and + SZ_BufftoBuffDecompress for truncated input. +- Out-of-bounds read in the decoder for fundamental sequences of 2^31 + or more zero bits reported by Haind03 (#64). +- Corrupted split blocks decoded to garbage instead of returning + AEC_DATA_ERROR. + ## [1.1.7] - 2026-05-19 ### Fixed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/CMakeLists.txt new/libaec-v1.1.8/CMakeLists.txt --- old/libaec-v1.1.7/CMakeLists.txt 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/CMakeLists.txt 2026-11-04 15:51:40.000000000 +0100 @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.26...3.31) -project(libaec LANGUAGES C VERSION 1.1.7) +project(libaec LANGUAGES C VERSION 1.1.8) option(BUILD_SHARED_LIBS "OFF: do not build shared libraries. ON (default): build shared libraries" ON) option(BUILD_STATIC_LIBS "OFF: do not build static libraries. ON (default): build static libraries" ON) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/README.md new/libaec-v1.1.8/README.md --- old/libaec-v1.1.7/README.md 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/README.md 2026-11-04 15:51:40.000000000 +0100 @@ -40,7 +40,7 @@ ## SZIP Compatibility -[Libaec can replace SZIP](README.SZIP). +Libaec contains libsz which can replace SZIP. ## Encoding diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/configure.ac new/libaec-v1.1.8/configure.ac --- old/libaec-v1.1.7/configure.ac 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/configure.ac 2026-11-04 15:51:40.000000000 +0100 @@ -2,7 +2,7 @@ m4_define([VERSION_MAJOR], [1]) m4_define([VERSION_MINOR], [1]) -m4_define([VERSION_PATCH], [7]) +m4_define([VERSION_PATCH], [8]) AC_INIT([libaec],[VERSION_MAJOR.VERSION_MINOR.VERSION_PATCH],[[email protected]]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/doc/README.SZIP new/libaec-v1.1.8/doc/README.SZIP --- old/libaec-v1.1.7/doc/README.SZIP 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/doc/README.SZIP 1970-01-01 01:00:00.000000000 +0100 @@ -1,15 +0,0 @@ -********************************************************************** - SZIP compatibility -********************************************************************** - -Libaec includes a free drop-in replacement for the SZIP -library[1]. Just replace SZIP's shared library libsz.so* with -libaec.so* and libsz.so* from libaec. For Windows the DLLs are called -SZIP.DLL and AEC.DLL. Code which is dynamically linked with SZIP such -as HDF5 should continue to work with libaec. No re-compilation -required. - -HDF5 files which contain SZIP encoded data can be decoded by HDF5 -using libaec and vice versa. - -[1] http://www.hdfgroup.org/doc_resource/SZIP/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/packaging/libaec-config.cmake new/libaec-v1.1.8/packaging/libaec-config.cmake --- old/libaec-v1.1.7/packaging/libaec-config.cmake 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/packaging/libaec-config.cmake 2026-11-04 15:51:40.000000000 +0100 @@ -12,14 +12,27 @@ # set(libaec_USE_STATIC_LIBS ON) # find_package(libaec CONFIG) # +# Components +# ---------- +# The installed library flavors are reported as find_package +# components. This can be used to require a certain flavor to be +# present. +# Example: +# find_package(libaec CONFIG REQUIRED COMPONENTS static) +# +# Recognized components are "shared" and "static". Requesting a +# component does not select it, use libaec_USE_STATIC_LIBS for that. +# # This will define the following variables: # -# libaec_FOUND - True if the system has the AEC library. -# libaec_VERSION - The version of the AEC library which was found. -# SZIP_FOUND - True if the system has the SZIP library. -# SZIP_VERSION - The version of the SZIP library which was found. -# SZIP_LIBRARIES - All the required libraries to make use of SZIP. -# SZIP_INCLUDE_DIR - SZIP include directory. +# libaec_FOUND - True if the system has the AEC library. +# libaec_VERSION - The version of the AEC library which was found. +# libaec_shared_FOUND - True if the shared libraries were installed. +# libaec_static_FOUND - True if the static libraries were installed. +# SZIP_FOUND - True if the system has the SZIP library. +# SZIP_VERSION - The version of the SZIP library which was found. +# SZIP_LIBRARIES - All the required libraries to make use of SZIP. +# SZIP_INCLUDE_DIR - SZIP include directory. # # and the following imported targets: # @@ -35,33 +48,54 @@ # AEC library (according to the value of # libaec_USE_STATIC_LIBS). -# Alias static or shared targets depending on libaec_USE_STATIC_LIBS -if(libaec_USE_STATIC_LIBS) - include(${CMAKE_CURRENT_LIST_DIR}/libaec_static-targets.cmake) - if(TARGET libaec::aec-static AND TARGET libaec::sz-static) - if(NOT TARGET libaec::aec AND NOT TARGET libaec::sz) - add_library(libaec::aec ALIAS libaec::aec-static) - add_library(libaec::sz ALIAS libaec::sz-static) - endif() +# A targets file is only installed for a flavor which has actually been +# built. Both includes are therefore optional. +include(${CMAKE_CURRENT_LIST_DIR}/libaec_shared-targets.cmake OPTIONAL) +include(${CMAKE_CURRENT_LIST_DIR}/libaec_static-targets.cmake OPTIONAL) + +# Report the installed flavors as components. Callers can query these +# variables directly, they are also used for the component check below. +foreach(_flavor shared static) + if(TARGET libaec::aec-${_flavor} AND TARGET libaec::sz-${_flavor}) + set(${CMAKE_FIND_PACKAGE_NAME}_${_flavor}_FOUND TRUE) else() - set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE - "STATIC versions of libaec::aec and libaec::sz not found.") + set(${CMAKE_FIND_PACKAGE_NAME}_${_flavor}_FOUND FALSE) + endif() +endforeach() +unset(_flavor) + +# Honor components requested by the caller. Config files have to do +# this themselves, find_package() only provides the request. +foreach(_comp IN LISTS ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS) + if(NOT ${CMAKE_FIND_PACKAGE_NAME}_${_comp}_FOUND + AND ${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED_${_comp}) + string(APPEND ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE + "Required component ${_comp} not found. ") set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE) endif() +endforeach() +unset(_comp) + +# Alias static or shared targets depending on libaec_USE_STATIC_LIBS +if(libaec_USE_STATIC_LIBS) + set(_libaec_flavor static) else() - include(${CMAKE_CURRENT_LIST_DIR}/libaec_shared-targets.cmake) + set(_libaec_flavor shared) +endif() - if(TARGET libaec::aec-shared AND TARGET libaec::sz-shared) - if(NOT TARGET libaec::aec AND NOT TARGET libaec::sz) - add_library(libaec::aec ALIAS libaec::aec-shared) - add_library(libaec::sz ALIAS libaec::sz-shared) - endif() - else() - set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE - "SHARED versions of libaec::aec and libaec::sz not found.") - set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE) +if(${CMAKE_FIND_PACKAGE_NAME}_${_libaec_flavor}_FOUND) + if(NOT TARGET libaec::aec AND NOT TARGET libaec::sz) + add_library(libaec::aec ALIAS libaec::aec-${_libaec_flavor}) + add_library(libaec::sz ALIAS libaec::sz-${_libaec_flavor}) endif() +else() + string(TOUPPER ${_libaec_flavor} _libaec_flavor_uc) + string(APPEND ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE + "${_libaec_flavor_uc} versions of libaec::aec and libaec::sz not found.") + set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE) + unset(_libaec_flavor_uc) endif() +unset(_libaec_flavor) if(TARGET libaec::sz) get_target_property(SZIP_INCLUDE_DIR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/src/CMakeLists.txt new/libaec-v1.1.8/src/CMakeLists.txt --- old/libaec-v1.1.7/src/CMakeLists.txt 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/src/CMakeLists.txt 2026-11-04 15:51:40.000000000 +0100 @@ -43,7 +43,7 @@ # Shared libaec versioning set(libaec_VERSION_MAJOR 0) set(libaec_VERSION_MINOR 1) - set(libaec_VERSION_PATCH 7) + set(libaec_VERSION_PATCH 8) # libtool compatible versioning for Mach-O math(EXPR libaec_MACHO_COMPATIBILITY_VERSION diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/src/Makefile.am new/libaec-v1.1.8/src/Makefile.am --- old/libaec-v1.1.7/src/Makefile.am 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/src/Makefile.am 2026-11-04 15:51:40.000000000 +0100 @@ -5,7 +5,7 @@ libaec_la_SOURCES = encode.c encode_accessors.c decode.c vector.c\ encode.h encode_accessors.h decode.h vector.h libaec_la_CPPFLAGS = $(AM_CPPFLAGS) -DLIBAEC_BUILD $(LIBAEC_SHARED) -libaec_la_LDFLAGS = -version-info 1:7:1 -no-undefined +libaec_la_LDFLAGS = -version-info 1:8:1 -no-undefined libsz_la_SOURCES = sz_compat.c libsz_la_LIBADD = libaec.la libsz_la_CPPFLAGS = $(AM_CPPFLAGS) -DLIBAEC_BUILD $(LIBAEC_SHARED) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/src/decode.c new/libaec-v1.1.8/src/decode.c --- old/libaec-v1.1.7/src/decode.c 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/src/decode.c 2026-11-04 15:51:40.000000000 +0100 @@ -469,25 +469,27 @@ if (BUFFERSPACE(strm)) { int k = state->id - 1; size_t binary_part = (k * state->encoded_block_size) / 8 + 9; - - /* Check input availability before any side effects on rsip so - * that a premature M_ERROR doesn't leave rsip partially - * advanced and corrupt the rsi_buffer on a subsequent call. */ - if (k && strm->avail_in < binary_part) - return M_ERROR; + uint32_t *rsip = state->rsip; if (state->ref) - *state->rsip++ = direct_get(strm, strm->bits_per_sample); + *rsip++ = direct_get(strm, strm->bits_per_sample); for (size_t i = 0; i < state->encoded_block_size; i++) - state->rsip[i] = direct_get_fs(strm) << k; + rsip[i] = direct_get_fs(strm) << k; + + /* Long fundamental sequences in corrupted data may have + * consumed the input needed for the binary part. Only + * advance state->rsip once we know the block is complete. */ + if (k && strm->avail_in < binary_part) + return M_ERROR; if (k) { for (size_t i = 0; i < state->encoded_block_size; i++) - *state->rsip++ += direct_get(strm, k); + *rsip++ += direct_get(strm, k); } else { - state->rsip += state->encoded_block_size; + rsip += state->encoded_block_size; } + state->rsip = rsip; strm->avail_out -= state->out_blklen; state->mode = m_next_cds; @@ -558,7 +560,7 @@ struct internal_state *state = strm->state; while(state->sample_counter < strm->block_size) { - int32_t m; + uint32_t m; int32_t d1; if (fs_ask(strm) == 0) return M_EXIT; @@ -671,6 +673,13 @@ return M_CONTINUE; } +static int m_error(struct aec_stream *strm) +{ + /* Stay in error state. Resuming after a data error could leave + * a partial block in rsi_buffer and overrun it. */ + return M_ERROR; +} + static void create_se_table(int *table) { int k = 0; @@ -827,8 +836,10 @@ status = state->mode(strm); } while (status == M_CONTINUE); - if (status == M_ERROR) + if (status == M_ERROR) { + state->mode = m_error; return AEC_DATA_ERROR; + } if (status == M_EXIT && strm->avail_out > 0 && strm->avail_out < state->bytes_per_sample) { @@ -949,6 +960,12 @@ return status; } + /* Truncated input leaves part of out_tmp uninitialized */ + if (strm_tmp.total_out < pos % rsi_size + size) { + free(out_tmp); + return AEC_DATA_ERROR; + } + memcpy(strm->next_out, out_tmp + (pos - rsi_n * rsi_size), size); strm->next_out += size; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/src/sz_compat.c new/libaec-v1.1.8/src/sz_compat.c --- old/libaec-v1.1.7/src/sz_compat.c 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/src/sz_compat.c 2026-11-04 15:51:40.000000000 +0100 @@ -70,6 +70,20 @@ return 1; } +static int check_params(const SZ_com_t *param) +{ + /* SZ_com_t fields are signed, so reject negative values here + * before they are converted to unsigned sizes. */ + if (param->pixels_per_scanline <= 0 + || param->pixels_per_scanline > 4096 + || param->pixels_per_block <= 0 + || param->pixels_per_block & 1 + || param->bits_per_pixel <= 0 + || (param->bits_per_pixel > 32 && param->bits_per_pixel != 64)) + return SZ_PARAM_ERROR; + return SZ_OK; +} + static void interleave_buffer(void *dest, const void *src, size_t n, size_t wordsize) { @@ -144,12 +158,7 @@ size_t padbuf_size; size_t padding_size; - if (param->pixels_per_scanline == 0 - || param->pixels_per_scanline > 4096 - || param->pixels_per_block == 0 - || param->pixels_per_block & 1 - || param->bits_per_pixel == 0 - || (param->bits_per_pixel > 32 && param->bits_per_pixel != 64)) + if (check_params(param) != SZ_OK) return SZ_PARAM_ERROR; strm.block_size = param->pixels_per_block; @@ -233,12 +242,7 @@ size_t total_out; size_t scanlines; - if (param->pixels_per_scanline == 0 - || param->pixels_per_scanline > 4096 - || param->pixels_per_block == 0 - || param->pixels_per_block & 1 - || param->bits_per_pixel == 0 - || (param->bits_per_pixel > 32 && param->bits_per_pixel != 64)) + if (check_params(param) != SZ_OK) return SZ_PARAM_ERROR; strm.block_size = param->pixels_per_block; @@ -286,13 +290,14 @@ goto CLEANUP; if (pad_scanline) { - size_t padding_size = - (strm.rsi * strm.block_size - param->pixels_per_scanline) - * pixel_size; - remove_padding(buf, strm.total_out, - param->pixels_per_scanline * pixel_size, - padding_size, pixel_size); - total_out = scanlines * param->pixels_per_scanline * pixel_size; + size_t line_size = param->pixels_per_scanline * pixel_size; + size_t padded_line_size = strm.rsi * strm.block_size * pixel_size; + remove_padding(buf, strm.total_out, line_size, + padded_line_size - line_size, pixel_size); + /* Only count what was actually decoded. Truncated input + * leaves the rest of buf uninitialized. */ + total_out = strm.total_out / padded_line_size * line_size + + MIN(strm.total_out % padded_line_size, line_size); } else { total_out = strm.total_out; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/tests/CMakeLists.txt new/libaec-v1.1.8/tests/CMakeLists.txt --- old/libaec-v1.1.7/tests/CMakeLists.txt 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/tests/CMakeLists.txt 2026-11-04 15:51:40.000000000 +0100 @@ -13,6 +13,9 @@ add_executable(check_long_fs check_long_fs.c) target_link_libraries(check_long_fs PUBLIC check_aec libaec::aec) add_test(NAME check_long_fs COMMAND check_long_fs) +add_executable(check_corrupt_input check_corrupt_input.c) +target_link_libraries(check_corrupt_input PUBLIC check_aec libaec::aec) +add_test(NAME check_corrupt_input COMMAND check_corrupt_input) add_executable(check_szcomp check_szcomp.c) target_link_libraries(check_szcomp PUBLIC check_aec libaec::sz) @@ -24,6 +27,10 @@ COMMAND_EXPAND_LISTS ) +add_executable(check_sz_input check_sz_input.c) +target_link_libraries(check_sz_input PUBLIC check_aec libaec::sz) +add_test(NAME check_sz_input COMMAND check_sz_input) + add_executable(check_rsi_block_access check_rsi_block_access.c) target_link_libraries(check_rsi_block_access PUBLIC check_aec libaec::aec) add_test(NAME check_rsi_block_access COMMAND check_rsi_block_access) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/tests/Makefile.am new/libaec-v1.1.8/tests/Makefile.am --- old/libaec-v1.1.7/tests/Makefile.am 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/tests/Makefile.am 2026-11-04 15:51:40.000000000 +0100 @@ -1,13 +1,15 @@ AUTOMAKE_OPTIONS = color-tests AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include TESTS = check_code_options check_buffer_sizes check_long_fs \ -check_seeking check_rsi_block_access szcomp.sh sampledata.sh +check_corrupt_input check_sz_input check_seeking check_rsi_block_access \ +szcomp.sh sampledata.sh TEST_EXTENSIONS = .sh CLEANFILES = test.dat test.rz check_LTLIBRARIES = libcheck_aec.la libcheck_aec_la_SOURCES = check_aec.c check_aec.h check_PROGRAMS = check_code_options check_buffer_sizes check_long_fs \ -check_szcomp check_seeking check_rsi_block_access +check_corrupt_input check_szcomp check_sz_input check_seeking \ +check_rsi_block_access check_code_options_SOURCES = check_code_options.c check_aec.h \ $(top_builddir)/include/libaec.h @@ -18,6 +20,9 @@ check_long_fs_SOURCES = check_long_fs.c check_aec.h \ $(top_builddir)/include/libaec.h +check_corrupt_input_SOURCES = check_corrupt_input.c check_aec.h \ +$(top_builddir)/include/libaec.h + check_seeking_SOURCES = check_seeking.c check_aec.h \ $(top_builddir)/include/libaec.h @@ -29,6 +34,10 @@ LDADD = libcheck_aec.la $(top_builddir)/src/libaec.la check_szcomp_LDADD = $(top_builddir)/src/libsz.la +check_sz_input_SOURCES = check_sz_input.c check_aec.h \ +$(top_srcdir)/include/szlib.h +check_sz_input_LDADD = libcheck_aec.la $(top_builddir)/src/libsz.la + EXTRA_DIST = sampledata.sh szcomp.sh CMakeLists.txt szcomp.log: sampledata.log diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/tests/check_corrupt_input.c new/libaec-v1.1.8/tests/check_corrupt_input.c --- old/libaec-v1.1.7/tests/check_corrupt_input.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libaec-v1.1.8/tests/check_corrupt_input.c 2026-11-04 15:51:40.000000000 +0100 @@ -0,0 +1,239 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "check_aec.h" + +static int check_split_truncated_binary_part(void) +{ + /* + A single split-coded block (ID 010, k = 1) followed by zeros. + The input is long enough for the decoder's fast path, but the + zero bits are read as one long fundamental sequence that + consumes the input needed for the binary part. The decoder + must report a data error instead of returning garbage. + */ + unsigned char in[32] = {0x40}; + unsigned char out[8]; + struct aec_stream strm; + int status; + + printf("Checking split block with exhausted binary part ... "); + + memset(&strm, 0, sizeof(strm)); + strm.bits_per_sample = 8; + strm.block_size = 8; + strm.rsi = 1; + strm.flags = 0; + strm.next_in = in; + strm.avail_in = sizeof(in); + strm.next_out = out; + strm.avail_out = sizeof(out); + + status = aec_buffer_decode(&strm); + if (status != AEC_DATA_ERROR) { + printf("%s: expected AEC_DATA_ERROR, got %i\n", CHECK_FAIL, status); + return 99; + } + + printf("%s\n", CHECK_PASS); + return 0; +} + +static int check_se_huge_fs_small_output(void) +{ + /* + A Second Extension block (ID 000, then 1) whose first + fundamental sequence is longer than 2^31 zero bits. A one-byte + output buffer forces the decoder's slow path. The FS length + must not wrap to a negative table index; the decoder must + report a data error instead of reading outside se_table. + */ + const size_t zero_len = 1 << 20; + const size_t zero_chunks = (1UL << 31) / 8 / zero_len; + unsigned char head = 0x10; + unsigned char tail = 0xff; + unsigned char *zeros; + unsigned char out[1]; + struct aec_stream strm; + int status; + + printf("Checking second extension with huge fundamental sequence ... "); + + zeros = calloc(zero_len, 1); + if (zeros == NULL) { + fprintf(stderr, "Not enough memory.\n"); + return 99; + } + + memset(&strm, 0, sizeof(strm)); + strm.bits_per_sample = 8; + strm.block_size = 8; + strm.rsi = 1; + strm.flags = 0; + + if (aec_decode_init(&strm) != AEC_OK) { + printf("%s: init failed\n", CHECK_FAIL); + free(zeros); + return 99; + } + + strm.next_out = out; + strm.avail_out = sizeof(out); + strm.next_in = &head; + strm.avail_in = 1; + status = aec_decode(&strm, AEC_NO_FLUSH); + + for (size_t i = 0; i < zero_chunks && status == AEC_OK; i++) { + strm.next_in = zeros; + strm.avail_in = zero_len; + status = aec_decode(&strm, AEC_NO_FLUSH); + } + + if (status == AEC_OK) { + strm.next_in = &tail; + strm.avail_in = 1; + status = aec_decode(&strm, AEC_NO_FLUSH); + } + + aec_decode_end(&strm); + free(zeros); + + if (status != AEC_DATA_ERROR) { + printf("%s: expected AEC_DATA_ERROR, got %i\n", CHECK_FAIL, status); + return 99; + } + + printf("%s\n", CHECK_PASS); + return 0; +} + +static void put_bits(unsigned char *buf, size_t *bitp, + unsigned int data, int n) +{ + while (n--) { + if ((data >> n) & 1) + buf[*bitp >> 3] |= 0x80 >> (*bitp & 7); + (*bitp)++; + } +} + +static void put_fs(unsigned char *buf, size_t *bitp, unsigned int fs) +{ + *bitp += fs; + put_bits(buf, bitp, 1, 1); +} + +static int check_decode_after_error(void) +{ + /* + A Second Extension block that decodes one pair of samples and + then fails on an FS beyond the SE table, followed by valid + blocks. The first call fails after part of the block has been + written to rsi_buffer. Calling aec_decode() again must keep + failing instead of decoding more blocks past the end of + rsi_buffer. + */ + unsigned char in[128]; + unsigned char out[1024]; + size_t bitp = 0; + struct aec_stream strm; + int status; + + printf("Checking decoding after data error ... "); + + memset(in, 0, sizeof(in)); + put_bits(in, &bitp, 1, 4); + put_fs(in, &bitp, 0); + put_fs(in, &bitp, 91); + for (int b = 0; b < 8; b++) { + put_bits(in, &bitp, 1, 4); + for (int i = 0; i < 4; i++) + put_fs(in, &bitp, 0); + } + + memset(&strm, 0, sizeof(strm)); + strm.bits_per_sample = 8; + strm.block_size = 8; + strm.rsi = 1; + strm.flags = 0; + + if (aec_decode_init(&strm) != AEC_OK) { + printf("%s: init failed\n", CHECK_FAIL); + return 99; + } + + strm.next_in = in; + strm.avail_in = sizeof(in); + strm.next_out = out; + strm.avail_out = sizeof(out); + + status = aec_decode(&strm, AEC_FLUSH); + if (status == AEC_DATA_ERROR) + status = aec_decode(&strm, AEC_FLUSH); + aec_decode_end(&strm); + + if (status != AEC_DATA_ERROR) { + printf("%s: expected AEC_DATA_ERROR, got %i\n", CHECK_FAIL, status); + return 99; + } + + printf("%s\n", CHECK_PASS); + return 0; +} + +static int check_decode_range_truncated(void) +{ + /* + An uncompressed block ID without any sample data. The + requested range can't be decoded, so aec_decode_range() must + report a data error instead of returning uninitialized + memory. + */ + unsigned char in[1] = {0xe0}; + unsigned char out[64]; + size_t offsets[1] = {0}; + struct aec_stream strm; + int status; + + printf("Checking range decoding of truncated input ... "); + + memset(&strm, 0, sizeof(strm)); + strm.bits_per_sample = 8; + strm.block_size = 8; + strm.rsi = 8; + strm.flags = 0; + strm.next_in = in; + strm.avail_in = sizeof(in); + + if (aec_decode_init(&strm) != AEC_OK) { + printf("%s: init failed\n", CHECK_FAIL); + return 99; + } + + strm.next_out = out; + strm.avail_out = sizeof(out); + status = aec_decode_range(&strm, offsets, 1, 0, sizeof(out)); + aec_decode_end(&strm); + + if (status != AEC_DATA_ERROR) { + printf("%s: expected AEC_DATA_ERROR, got %i\n", CHECK_FAIL, status); + return 99; + } + + printf("%s\n", CHECK_PASS); + return 0; +} + +int main(void) +{ + int status = check_split_truncated_binary_part(); + if (status) + return status; + status = check_se_huge_fs_small_output(); + if (status) + return status; + status = check_decode_after_error(); + if (status) + return status; + return check_decode_range_truncated(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/tests/check_rsi_block_access.c new/libaec-v1.1.8/tests/check_rsi_block_access.c --- old/libaec-v1.1.7/tests/check_rsi_block_access.c 2026-05-19 12:20:48.000000000 +0200 +++ new/libaec-v1.1.8/tests/check_rsi_block_access.c 2026-11-04 15:51:40.000000000 +0100 @@ -70,7 +70,7 @@ } size_t nvalues = ctx->obuf_len / nbytes; - size_t mask = (1 << (ctx->bits_per_sample - 1))-1; + size_t mask = ((size_t)1 << (ctx->bits_per_sample - 1)) - 1; for (size_t i = 0; i < nvalues; i++) { size_t value = rand() & mask; @@ -96,7 +96,7 @@ } size_t nvalues = ctx->obuf_len / nbytes; - size_t max_value = 1 << (ctx->bits_per_sample - 1); + size_t max_value = (size_t)1 << (ctx->bits_per_sample - 1); for (size_t i = 0; i < nvalues; i++) { size_t value = i % max_value; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libaec-v1.1.7/tests/check_sz_input.c new/libaec-v1.1.8/tests/check_sz_input.c --- old/libaec-v1.1.7/tests/check_sz_input.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libaec-v1.1.8/tests/check_sz_input.c 2026-11-04 15:51:40.000000000 +0100 @@ -0,0 +1,108 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "szlib.h" +#include "check_aec.h" + +#define NPIXELS 1000 + +static int check_negative_params(void) +{ + /* + SZ_com_t fields are signed. Negative values must be rejected + before they are used to size the padding buffer. + */ + SZ_com_t bad[] = { + {0, 8, 8, -100}, + {0, 8, -2, 10}, + {0, -8, 8, 10}, + }; + unsigned char source[200]; + unsigned char dest[4096]; + + printf("Checking negative SZ parameters ... "); + + memset(source, 0, sizeof(source)); + for (size_t i = 0; i < sizeof(bad) / sizeof(bad[0]); i++) { + size_t destLen = sizeof(dest); + int status = SZ_BufftoBuffCompress(dest, &destLen, + source, sizeof(source), &bad[i]); + if (status != SZ_PARAM_ERROR) { + printf("%s: compress %zu: expected SZ_PARAM_ERROR, got %i\n", + CHECK_FAIL, i, status); + return 99; + } + destLen = sizeof(dest); + status = SZ_BufftoBuffDecompress(dest, &destLen, + source, sizeof(source), &bad[i]); + if (status != SZ_PARAM_ERROR) { + printf("%s: decompress %zu: expected SZ_PARAM_ERROR, got %i\n", + CHECK_FAIL, i, status); + return 99; + } + } + + printf("%s\n", CHECK_PASS); + return 0; +} + +static int check_truncated_padded_scanlines(void) +{ + /* + Scanlines that are not a multiple of the block size take the + padding path in SZ_BufftoBuffDecompress. With truncated input + destLen must only cover the decoded pixels, not the whole + requested buffer. + */ + SZ_com_t param = {SZ_MSB_OPTION_MASK | SZ_NN_OPTION_MASK, 8, 8, 10}; + unsigned char source[NPIXELS]; + unsigned char comp[2 * NPIXELS]; + unsigned char dest[NPIXELS]; + size_t compLen = sizeof(comp); + size_t destLen; + int status; + + printf("Checking SZ decompression of truncated padded scanlines ... "); + + for (size_t i = 0; i < NPIXELS; i++) + source[i] = (unsigned char)(i * i / 7); + + status = SZ_BufftoBuffCompress(comp, &compLen, + source, sizeof(source), ¶m); + if (status != SZ_OK) { + printf("%s: compress failed with %i\n", CHECK_FAIL, status); + return 99; + } + + destLen = sizeof(dest); + status = SZ_BufftoBuffDecompress(dest, &destLen, comp, compLen, ¶m); + if (status != SZ_OK || destLen != NPIXELS + || memcmp(source, dest, NPIXELS) != 0) { + printf("%s: full round trip failed\n", CHECK_FAIL); + return 99; + } + + destLen = sizeof(dest); + status = SZ_BufftoBuffDecompress(dest, &destLen, + comp, compLen / 2, ¶m); + if (status != SZ_OK) { + printf("%s: decompress failed with %i\n", CHECK_FAIL, status); + return 99; + } + if (destLen >= NPIXELS || memcmp(source, dest, destLen) != 0) { + printf("%s: destLen %zu doesn't match decoded data\n", + CHECK_FAIL, destLen); + return 99; + } + + printf("%s\n", CHECK_PASS); + return 0; +} + +int main(void) +{ + int status = check_negative_params(); + if (status) + return status; + return check_truncated_padded_scanlines(); +}
