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), &param);
+    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, &param);
+    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, &param);
+    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();
+}

Reply via email to