Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package dd_rescue for openSUSE:Factory 
checked in at 2026-10-20 12:36:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dd_rescue (Old)
 and      /work/SRC/openSUSE:Factory/.dd_rescue.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dd_rescue"

Tue Oct 20 12:36:02 2026 rev:69 rq:1386029 version:1.99.24

Changes:
--------
--- /work/SRC/openSUSE:Factory/dd_rescue/dd_rescue.changes      2026-10-06 
19:13:53.310137775 +0200
+++ /work/SRC/openSUSE:Factory/.dd_rescue.new.3698736/dd_rescue.changes 
2026-10-20 12:36:17.970447372 +0200
@@ -1,0 +2,12 @@
+Sun Oct 18 10:59:19 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to version 1.99.24:
+  * 1.99.23: plugin close errors are reported as FATAL and always
+    reflected in the exit code; fixed positioning when overlapping
+    copies are detected and the copy direction is changed.
+  * 1.99.24: documentation improvements and fine-tuning of the
+    remaining time estimates.
+- Spec cleanup: https sources, pkgconfig-style BuildRequires,
+  drop obsolete Group tags.
+
+-------------------------------------------------------------------

Old:
----
  dd_rescue-1.99.22.tar.bz2
  dd_rescue-1.99.22.tar.bz2.asc

New:
----
  dd_rescue-1.99.24.tar.bz2
  dd_rescue-1.99.24.tar.bz2.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dd_rescue.spec ++++++
--- /var/tmp/diff_new_pack.ZkQiFb/_old  2026-10-20 12:36:18.747479766 +0200
+++ /var/tmp/diff_new_pack.ZkQiFb/_new  2026-10-20 12:36:18.749479850 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package dd_rescue
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -21,31 +21,42 @@
 %define _lto_cflags %{nil}
 %endif
 Name:           dd_rescue
-Version:        1.99.22
+Version:        1.99.24
 Release:        0
 Summary:        Data copying in the presence of I/O Errors
 License:        GPL-2.0-only OR GPL-3.0-only
-Group:          System/Base
-URL:            http://www.garloff.de/kurt/linux/ddrescue/
-Source0:        
http://garloff.de/kurt/linux/ddrescue/%{name}-%{version}.tar.bz2
-Source1:        
http://garloff.de/kurt/linux/ddrescue/%{name}-%{version}.tar.bz2.asc
+URL:            https://www.garloff.de/kurt/linux/ddrescue/
+Source0:        
https://garloff.de/kurt/linux/ddrescue/%{name}-%{version}.tar.bz2
+Source1:        
https://garloff.de/kurt/linux/ddrescue/%{name}-%{version}.tar.bz2.asc
 Source2:        %{name}.keyring
 Source99:       %{name}.changes
 # PATCH-FIX-OPENSUSE dd_rescue-ssp-strong.patch -- the libddr_lzo.po rule
 # appends basic -fstack-protector which downgrades the distro
 # -fstack-protector-strong from %%optflags; use strong instead
 Patch0:         dd_rescue-ssp-strong.patch
-# PATCH-FIX-UPSTREAM no-python2.patch sf#ddrescue#4 [email protected]
-# Remove dependency on python2
-BuildRequires:  autoconf
-BuildRequires:  libattr-devel
-# Workaround for bsc#1193438
-BuildRequires:  libopenssl-devel
-BuildRequires:  lzo-devel
 BuildRequires:  lzop
 BuildRequires:  pkgconfig
 BuildRequires:  python3-base
-BuildRequires:  xz-devel
+# PATCH-FIX-UPSTREAM no-python2.patch sf#ddrescue#4 [email protected]
+# Remove dependency on python2
+BuildRequires:  perl(Autom4te::C4che)
+BuildRequires:  perl(Autom4te::ChannelDefs)
+BuildRequires:  perl(Autom4te::Channels)
+BuildRequires:  perl(Autom4te::Config)
+BuildRequires:  perl(Autom4te::Configure_ac)
+BuildRequires:  perl(Autom4te::FileUtils)
+BuildRequires:  perl(Autom4te::General)
+BuildRequires:  perl(Autom4te::Getopt)
+BuildRequires:  perl(Autom4te::Request)
+BuildRequires:  perl(Autom4te::XFile)
+BuildRequires:  pkgconfig(libattr)
+# Workaround for bsc#1193438
+BuildRequires:  pkgconfig(libcrypto)
+BuildRequires:  pkgconfig(liblzma)
+BuildRequires:  pkgconfig(libopenssl)
+BuildRequires:  pkgconfig(libssl)
+BuildRequires:  pkgconfig(lzo2)
+BuildRequires:  pkgconfig(openssl)
 Requires:       bc
 Recommends:     dd_rescue-crypt
 Recommends:     dd_rescue-lzo
@@ -74,7 +85,6 @@
 
 %package crypt
 Summary:        Crypt plugin for dd_rescue
-Group:          System/Base
 Requires:       dd_rescue = %{version}
 
 %description crypt
@@ -91,7 +101,6 @@
 
 %package lzo
 Summary:        LZO plugin for dd_rescue
-Group:          System/Base
 Requires:       dd_rescue = %{version}
 
 %description lzo
@@ -117,7 +126,6 @@
 
 %package lzma
 Summary:        LZMA (xz) de/compression plugin for dd_rescue
-Group:          System/Base
 Requires:       dd_rescue = %{version}
 
 %description lzma
@@ -130,11 +138,6 @@
 a bad idea to feed it with untrusted data, especially when running
 with elevated privileges.
 
-Authors:
---------
-    Dmitrii Ivanov <[email protected]>
-    Kurt Garloff <[email protected]>
-
 %prep
 %autosetup -p1
 

++++++ dd_rescue-1.99.22.tar.bz2 -> dd_rescue-1.99.24.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/Makefile 
new/dd_rescue-1.99.24/Makefile
--- old/dd_rescue-1.99.22/Makefile      2025-12-07 18:50:24.911983400 +0100
+++ new/dd_rescue-1.99.24/Makefile      2026-10-09 14:15:02.000000000 +0200
@@ -1,7 +1,7 @@
 # (c) [email protected], 99/10/09, GNU GPL
 # (c) [email protected], 2010 -- 2021, GNU GPL v2 or v3
 
-VERSION = 1.99.22
+VERSION = 1.99.24
 
 DESTDIR = 
 THISMKFILE := $(lastword $(MAKEFILE_LIST))
@@ -9,7 +9,7 @@
 
 CC = gcc
 SHELL := bash
-RPM_OPT_FLAGS ?= -Os -Wall -g -D_FORTIFY_SOURCE=2
+RPM_OPT_FLAGS ?= -Os -Wall -g -D_FORTIFY_SOURCE=3
 CFLAGS = $(RPM_OPT_FLAGS) $(EXTRA_CFLAGS) -DHAVE_CONFIG_H -I .
 CFLAGS_OPT = $(CFLAGS) -O3
 INSTALL ?= install
@@ -35,7 +35,8 @@
 DDR_HEADERS = config.h $(SRCDIR)/random.h $(SRCDIR)/frandom.h $(SRCDIR)/list.h 
$(SRCDIR)/fmt_no.h $(SRCDIR)/find_nonzero.h $(SRCDIR)/archdep.h $(SRCDIR)/ffs.h 
$(SRCDIR)/fstrim.h $(SRCDIR)/ddr_plugin.h $(SRCDIR)/ddr_ctrl.h 
$(SRCDIR)/splice.h $(SRCDIR)/fallocate64.h $(SRCDIR)/pread64.h
 DOCDIR = $(prefix)/share/doc/packages
 INSTASROOT = -o root -g root
-LIB = lib
+#LIB = lib
+LIB=$(shell ldconfig -Nv 2>/dev/null | grep "^$(prefix)" | sed 's/:.*$$//' | 
head -n1 | sed "s@^$(prefix)/@@")
 LIBDIR = /usr/$(LIB)
 COMPILER = $(shell $(CC) --version | head -n1)
 ID = $(shell git describe --tags || cat REL-ID)
@@ -103,7 +104,7 @@
 endif
 ifeq ($(MACH),x86_64)
   ISX86 := 1
-  LIB = lib64
+  #LIB = lib64
 endif
 
 ifeq ($(ISX86), 1)
@@ -215,7 +216,7 @@
 endif  # ARM
 ifeq ($(MACH),aarch64)
 HAVE_RNG := $(shell echo "" | $(CC) -march=armv8.5-a+crypto+rng -xc - 2>&1 | 
grep unknown || echo 1)
-       LIB = lib64
+       #LIB = lib64
        OBJECTS2 = find_nonzero_arm64.o rdrand.o
        #POBJECTS2 = find_nonzero.po find_nonzero_arm64.po
        AES_ARM64_O = aes_arm64.o
@@ -481,7 +482,7 @@
 nocolor: $(SRCDIR)/dd_rescue.c $(DDR_HEADERS) $(OBJECTS) $(OBJECTS2)
        $(CC) $(CFLAGS) -DNO_COLORS=1 $(DEFINES) $< $(OUT) $(OBJECTS) 
$(OBJECTS2) $(EXTRA_LDFLAGS) $(RDYNAMIC)
 
-static: $(SRCDIR)/dd_rescue.c $(DDR_HEADERS) $(OBJECTS)
+static: $(SRCDIR)/dd_rescue.c $(DDR_HEADERS) $(OBJECTS) $(OBJECTS2)
        $(CC) $(CFLAGS) -DNO_LIBDL -DNO_LIBFALLOCATE -static $(DEFINES) $< 
$(OUT) $(OBJECTS) $(OBJECTS2) $(EXTRA_LDFLAGS)
 
 # Special pseudo targets
@@ -575,7 +576,7 @@
        $(INSTALL) $(INSTALLFLAGS) $(INSTASROOT) -m 755 $(LIBTARGETS) 
$(INSTALLLIBDIR)
        ln -sf libddr_hash.so $(INSTALLLIBDIR)/libddr_MD5.so
        mkdir -p $(MANDIR)/man1
-       $(INSTALL) $(INSTASROOT) -m 644 dd_rescue.1 ddr_lzo.1 ddr_crypt.1 
ddr_lzma.1 $(MANDIR)/man1/
+       $(INSTALL) $(INSTASROOT) -m 644 $(SRCDIR)/dd_rescue.1 
$(SRCDIR)/ddr_lzo.1 $(SRCDIR)/ddr_crypt.1 $(SRCDIR)/ddr_lzma.1 $(MANDIR)/man1/
        gzip -9f $(MANDIR)/man1/dd_rescue.1 $(MANDIR)/man1/ddr_lzo.1 
$(MANDIR)/man1/ddr_crypt.1 $(MANDIR)/man1/ddr_lzma.1
 
 check: $(TARGETS) find_nonzero md5 sha1 sha256 sha512 fmt_no
@@ -643,6 +644,20 @@
        $(VG) ./sha256 /dev/null
        $(VG) ./sha512 /dev/null
        rm -f TEST TEST2 HASH.TEST BB.log TEST.log
+       # Test with overlapping range: Write 1M random
+       @echo "***** dd_rescue auto-fixing overlapping copies *****"
+       $(VG) ./dd_rescue -L ./libddr_hash.so=sha256:outnm=HASH.TEST -m 1M -Z0 
TEST     # 0-1
+       $(VG) ./dd_rescue -s 0 -S 512k TEST TEST                                
        # auto-rev: 0.5-1.5
+       $(VG) ./dd_rescue -L ./libddr_hash.so=sha256:chknm=HASH.TEST -s 512k -S 
0 TEST /dev/null        # 0.5-1.5
+       $(VG) ./dd_rescue -s 1536k -S 1024k -r TEST TEST                        
        # auto-unrev: 0-1
+       $(VG) ./dd_rescue -L ./libddr_hash.so=sha256:chknm=HASH.TEST -s 0 -m 1M 
TEST /dev/null  # test 0-1
+       $(VG) ./dd_rescue -L ./libddr_hash.so=sha256:chknm=HASH.TEST -s 0 -S 1M 
-m 1M TEST TEST # copy 1-2
+       $(VG) ./dd_rescue -L ./libddr_hash.so=sha256:chknm=HASH.TEST -s 1M -S 0 
TEST /dev/null  # test 1-2
+       # This should unset reverse
+       $(VG) ./dd_rescue -S 1M -m 1M /dev/zero TEST                            
                # clear 1-2
+       $(VG) ./dd_rescue -r -s 1M -S 2M -m 1M TEST TEST                        
                # rev copy 1-2
+       $(VG) ./dd_rescue -L ./libddr_hash.so=sha256:chknm=HASH.TEST -s 1M -S 0 
TEST /dev/null  # test 1-2
+       rm -f TEST HASH.TEST
        if test $(HAVE_LZO) = 1; then $(MAKE) check_lzo; fi
        if test $(HAVE_LZO) = 1; then $(MAKE) check_lzo_algos; fi
        #if test $(HAVE_LZO) = 1; then $(MAKE) check_lzo_test; fi
@@ -884,6 +899,7 @@
 
 check_lzma: $(TARGETS)
        @echo "make check ... Pass VG=\"valgrind --options\" to use with 
valgrind"
+       @rm -f dd_rescue.xz dd_rescue_d first_test.txt first_test.txt.xz 
first_test_d.txt
        $(VG) ./dd_rescue -L ./libddr_lzma.so dd_rescue dd_rescue.xz
        $(VG) ./dd_rescue -L ./libddr_lzma.so dd_rescue.xz dd_rescue_d
        cmp dd_rescue dd_rescue_d
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/README.dd_rescue 
new/dd_rescue-1.99.24/README.dd_rescue
--- old/dd_rescue-1.99.22/README.dd_rescue      2025-12-07 14:13:21.363927040 
+0100
+++ new/dd_rescue-1.99.24/README.dd_rescue      2026-10-09 12:43:34.000000000 
+0200
@@ -1,7 +1,7 @@
 README file for dd_rescue
 =========================
 (c) [email protected], 10/99, GNU GPL 
-(c) [email protected]  2011-2015, GNU GPL v2 or v3
+(c) [email protected]  2011-2026, GNU GPL v2 or v3
 
 
 Description of dd_rescue
@@ -105,7 +105,7 @@
 -----------
 The source code does use the 64bit functions provided by glibc for file
 positioning. However, your kernel might not support it, so you might be
-unable to copy partitions larger then 2GB into a file.
+unable to copy partitions larger then 2GB into a file on old 32bit kernels.
 This program has been written using Linux and only tested on a couple of
 Linux systems. It should be possible to port it easily to other Un*x
 platforms, and I occasionally get hints from users of other *nix like
@@ -239,6 +239,10 @@
 * 1.99.22 brought better PRNG initialization on arm-v8.5a-rng. The reported
   rate is calculated better. The -@/--sparse-nonslow option allows to write
   0s only when the reads take long (for refreshing SSDs).
+* 1.99.23 ensures that plugin close errors are reported as FATAL and always
+  reflected in the exit code. It also fixes the positioning when overlapping
+  copies are detected and the copy direction is changed.
+* 1.99.24 brings docu improvement and fine-tuning on remaining time estimates.
 
 
 Building
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/README.plugin 
new/dd_rescue-1.99.24/README.plugin
--- old/dd_rescue-1.99.22/README.plugin 1970-01-01 01:00:00.000000000 +0100
+++ new/dd_rescue-1.99.24/README.plugin 2026-10-09 11:35:22.000000000 +0200
@@ -0,0 +1,117 @@
+# The dd_rescue plugin interface
+
+dd_rescue supports plugins. These can analyze and transform data.  Current
+examples are a ddr_hash plugin (analyzing the data only), ddr_crypt (doing AES
+en/decryption) and ddr_lzo and ddr_lzma plugins which do (de)compression.
+
+## The interface specification.
+
+Any plugin comes with a declaration of how it operates with ddr_plugin_t
+structure.
+
+It contains a name, a few settings and flags and a few callbacks.
+
+The following description will describe the flow and use this to explain the
+flags ...
+
+## Initialization phase
+
+User calls dd_rescue -L XXXX=parameters1[,YYYY=parameters2] [options] in out
+dd_rescue on initializations loads all plugins from left to right.  It uses
+dlopen to open libddr_XXXX.so. If XXXX is a full path (detected by finding a /
+in the name), the path will be loaded by dlopen instead.  All plugins are kept
+in a linked list.
+
+The ddr_plugin_t structure is found by searching for the ddr_plug symbol.
+
+The initialization fills in the logger structure, which the plugin can use to
+send log messages. If non-null, the init_callback will be called with the
+parameters and a sequence number communicating where in the food chain the
+plugin is. This init_callback is supposed to support a parameter help and
+output usage instructions in return. (Output should be created using the
+FPLOG() macro with INFO severity.)
+
+The init_callback should do all the parameter analysis, allocate internal
+storage etc. Note that no files have been opened yet when this happens.  The
+dd_rescue options have been parsed already at this point and can be analyzed or
+stored if needed.
+The ddr_plugin_t structure has a void pointer state meant to keep internal
+state. It's passed to all callbacks.
+
+Please see the ddr_plugin.h file for detailed interface declarations.
+
+The deinitialization happens with the release_callback which should free any
+storage allocated in init.
+
+The overall lifecycle is:
+   init_callback -> open_callback
+                                   -> block_callback [mnay times] 
+                 -> close_callback 
+-> release_callback
+
+## Open and Close
+
+Once the input and output files have been opened and the file positions been
+initialized, the open_callback is called. There are a few flags passed related
+to buffer handling, see below. The plugin can return a negative return code,
+signaling the main process to abort.
+
+The close_callback is called before input and output files are closed.
+Flushing any buffers however should have been done before, so this is often a
+no-op. Returning non-zero will be counted and reported as exit code from
+dd_rescue.
+
+## Processing the blocks
+
+dd_rescue reads blocks of data. Before writing the blocks out again, it
+calls all plugins' block_callback one after the other.
+
+Each plugin can process the buffer, optionally do adjustments to positions (in
+the file position struct) and pass back a modified or unmodified buffer that
+then gets passed on to the next plugin and ultimately to dd_rescue's output
+routine. The length ot output data (in *towr) can also be adjusted as needed.
+
+Plugins have a lot of freedom, which also makes it hard to guarantee
+correctness in all cases, where dd_rescue jumps around, e.g. due to repeated
+attempts to read hard-to-read data, jumping over unreadable blocks or jumping
+over zeroed blocks or doing reverse direction copies.  Plugins need to detect
+these things (by looking at the file position struct) or indicate via flags
+that they are not supporting certain modes of operation. See buffer handling
+section below.
+
+Fatal errors are reported by an FPLOG(FATAL) message and  raise(SIGQUIT) which
+will make dd_rescue abort the copy process and exit gracefully.
+
+The block_callback gets called once with eof=1 at the end, telling the plugin
+to flush buffers etc, so the regular dd_rescue write path can process the final
+bytes of the data produced this way.
+
+## Buffer handling
+
+In the easiest case, the plugin does not change the length of the buffer; if it
+can transform data in place (or not transform it at all), it can just return
+a pointer to the original buffer. Some plugins require a few bytes in front or
+behind the buffer but otherwise can deal without creating a block sized own
+buffer; this is indicated by slack_pre and slack_post; please see the comments
+in the struct to see how to state it in terms of block sizes.
+
+dd_rescue will collect all needs from the plugins and allocated an accordingly
+larger buffer that's passed along. The open_callback will pass on this
+information in case plugins do their own memory allocation and need to
+accomodate surrounding plugins.  The needs_align will also be considered by
+dd_rescue's buffer allocation.
+
+In the open_callback, the plugin will also be informed if plugins earlier or
+later in the chain do change the contents and the length of the data.
+
+## Non-linear motion
+
+dd_rescue might jump around; in particular it might jump over unreadable or
+zeroed (sparse detection) blocks or do a reverse direction copy.
+Plugins will need to detect this; typically by remembering the previous
+position and then doing whatever is needed for correct operation on a
+forward jump (assuming all jumped-over contents is zeroes).
+
+Plugins can indicate to not support sparse operation if they need to avoid
+the complexity of getting this right. Otherwise, the plugins hash, crypt,
+lzo all support rather complex cases.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/REL-ID new/dd_rescue-1.99.24/REL-ID
--- old/dd_rescue-1.99.22/REL-ID        2025-12-07 19:13:38.988580600 +0100
+++ new/dd_rescue-1.99.24/REL-ID        2026-10-09 14:46:34.000000000 +0200
@@ -1 +1 @@
-DD_RESCUE_1_99_22
+DD_RESCUE_1_99_24
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/TODO new/dd_rescue-1.99.24/TODO
--- old/dd_rescue-1.99.22/TODO  2021-04-14 10:23:02.000000000 +0200
+++ new/dd_rescue-1.99.24/TODO  2026-10-09 01:16:30.000000000 +0200
@@ -1,9 +1,9 @@
 Random ideas of future work on dd_rescue and plugins.
 =====================================================
 * Par2 module to add error correcting Reed-Solomon/Erasure Codes
-* ddr_lzo: More de/compression algorithms and file formats (.gz, .xz, lzip, 
zstd)
+* ddr_lzo: More de/compression algorithms and file formats (.gz, lzip, zstd)
 * Keep track of successfully copied blocks in dd_rescue itself to ease 
dd_rhelp's job ...
-* ddr_hash: More optimization (ARMv8), addition of SHA-3 (and SKEIN?) algs.
+* ddr_hash: Addition of SHA-3 (and SKEIN?) algs.
 * A networking plugin that allows (mostly unprotected?) network copies via TCP.
   This could also include support for (unencrypted) S3 protocol.
 * Leverage fault injection for more regression tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/checksum_file.c 
new/dd_rescue-1.99.24/checksum_file.c
--- old/dd_rescue-1.99.22/checksum_file.c       2024-08-22 19:41:01.135467510 
+0200
+++ new/dd_rescue-1.99.24/checksum_file.c       2026-08-07 08:14:51.000000000 
+0200
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <assert.h>
 
 #include "hash.h"
 #include "mybasename.h"
@@ -38,6 +39,7 @@
 {
        if (*sz == 0) {
                *bf = (char*)malloc(1024);
+               assert(*bf);
                *sz = 1024;
        }
        char* bret = fgets(*bf, *sz, f);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/dd_rescue.1 
new/dd_rescue-1.99.24/dd_rescue.1
--- old/dd_rescue-1.99.22/dd_rescue.1   2025-12-07 14:18:25.503462182 +0100
+++ new/dd_rescue-1.99.24/dd_rescue.1   2026-10-09 11:31:52.000000000 +0200
@@ -1,4 +1,4 @@
-.TH dd_rescue 1 "2025-06-24" "Kurt Garloff" "Data recovery and protection tool"
+.TH dd_rescue 1 "2026-10-09" "Kurt Garloff" "Data recovery and protection tool"
 .
 .SH NAME
 dd_rescue \- Data recovery and protection tool
@@ -573,6 +573,14 @@
 Some plugins may impose further restrictions w.r.t. alignment of data in
 the file or not using sparse detection.
 .br
+Plugins can error out on initialization, abort the copy process when hitting
+a fatal error during the process and also report errors upon finishing the
+process.
+.br
+You can chain several plugings, e.g. calculate a hash value, then compress,
+then encrypt. You could then reverse this by decrypting, decompressing, and
+hashing again (and comparing the hash values to check the integrity).
+.br
 See section 
 .B PLUGINS
 for an overview of available plugins.
@@ -1054,6 +1062,9 @@
 1.99.18-19 further improved it, with support for holes.
 1.99.20-21 hardened complex plugin chains and systematically handled
 issues when retries are necessary also in the write path.
+1.99.23-24 fixed a corner case where an error from a plugin got lost
+and where the overlap detection for same-file copies did not treat
+positions according to user expectations.
 .PP
 Some additional information can be found on
 .br
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/dd_rescue.c 
new/dd_rescue-1.99.24/dd_rescue.c
--- old/dd_rescue-1.99.22/dd_rescue.c   2025-12-07 13:29:02.893188128 +0100
+++ new/dd_rescue-1.99.24/dd_rescue.c   2026-10-09 13:48:33.000000000 +0200
@@ -496,8 +496,7 @@
 
 int call_plugins_close(opt_t *op, fstate_t *fst)
 {
-       //int errs = 0;
-       int maxerr = 0;
+       int errs = 0;
        int seq = 0;
        if (!plugins_opened)
                return 0;
@@ -506,17 +505,15 @@
                if (LISTDATA(plug).close_callback) {
                        int err = LISTDATA(plug).close_callback(fst->opos, 
&LISTDATA(plug).state);
                        if (err) {
-                               fplog(stderr, WARN, "Plugin %s(%i) reported 
error on close: %s!\n",
+                               fplog(stderr, FATAL, "Plugin %s(%i) reported 
error on close: %s!\n",
                                        LISTDATA(plug).name, seq, 
strerror(-err));
-                               //++errs;
-                               if (-err > maxerr)
-                                       maxerr = -err;
+                               ++errs;
                        }
                }
                ++seq;
                --plugins_opened;
        }
-       return /*errs*/maxerr;
+       return errs;
 }
 
 /** Call the plugin block processing chain ...
@@ -615,6 +612,7 @@
        }
 
        plug->logger = (plug_logger_t*)malloc(sizeof(plug_logger_t));
+       assert(plug->logger);
        snprintf(plug->logger->prefix, 24, "%s", plug->name);
        plug->logger->vfplog = vfplog;
 
@@ -1133,20 +1131,22 @@
         * floatrate32 takes the last 73 values to get over 90%.
         * On startup, we blend in the unweidghed total average.
         */
-       if (ctr < 4) {
-               floatrate4  = 4./(3./avgrate + 1./currate);
-               floatrate32 = 32./(31./avgrate + 1./currate);
-               ctr += incctr;
-       } else if (ctr < 32) {
-               floatrate4  = 4./(3./floatrate4 + 1./currate);
-               floatrate32 = 32./(31./avgrate + 1./currate);
-               ctr += incctr;
-       } else {
-               floatrate4  = 4./(3./floatrate4 + 1./currate);
-               floatrate32 = 32./(31./floatrate32 + 1./currate);
+       if (incctr) {
+               if (ctr < 4) {
+                       floatrate4  = 4./(3./avgrate + 1./currate);
+                       floatrate32 = 32./(31./avgrate + 1./currate);
+                       ctr += incctr;
+               } else if (ctr < 32) {
+                       floatrate4  = 4./(3./floatrate4 + 1./currate);
+                       floatrate32 = 32./(31./avgrate + 1./currate);
+                       ctr += incctr;
+               } else {
+                       floatrate4  = 4./(3./floatrate4 + 1./currate);
+                       floatrate32 = 32./(31./floatrate32 + 1./currate);
+               }
+               if (floatrate4 > maxrate)
+                       maxrate = floatrate4;
        }
-       if (floatrate4 > maxrate)
-               maxrate = floatrate4;
        if (nocol || (file != stderr && file != stdout)) {
                bold = ""; norm = "";
        }
@@ -1168,12 +1168,29 @@
                        nineright, 
                        fmt_int(9, 0, 1024, avgrate, bold, norm, 1),
                        fmt_int(3, 1, 10, 
(cl-startclock)/(t1*(CLOCKS_PER_SEC/1000)), bold, norm, 1));
-       if (fst->estxfer && avgrate > 0) {
+       if (fst->estxfer && avgrate > 0. && floatrate32 > 0.) {
+               static int lastsec = INT_MAX;
                int sec;
                if (in_report)
                        sec = 0.5 + t1;
-               else
-                       sec = 0.5 + 
2*(fst->estxfer-prg->xfer)/(avgrate+floatrate32);
+               else {
+                       /* Model: Assume floatrate32 predicts the next 8 
seconds well,
+                        * use the avg of avgrate and floatrate32 for the rest.
+                        * Also round up a bit more.
+                        */
+                       const loff_t remain = fst->estxfer - prg->xfer;
+                       const loff_t next8 = 8*floatrate32;
+                       if (remain < next8)
+                               sec = 0.75 + remain/floatrate32;
+                       else
+                               sec = 8.75 + 
2*(remain-next8)/(avgrate+floatrate32);
+                       /* Avoid jumping back 1s just b/c of one blip */
+                       if (sec - lastsec == 1) {
+                               sec = lastsec;
+                               lastsec += 1;
+                       } else
+                               lastsec = sec;
+               }
                int hour = sec / 3600;
                int min = (sec % 3600) / 60;
                sec = sec % 60;
@@ -1298,6 +1315,15 @@
        if (op->bbname == NULL)
                return;
        bbfile = fopen(op->bbname, "a");
+       /* We can't error out here if bbfile is not writable.
+        * TODO: WHen saving bad blocks is wanted, rather open bbfile before 
starting to copy
+        * (and error out if we can not write to the file then) and keep it 
open until the end.
+        */
+       if (!bbfile) {
+               fplog(stderr, WARN, "Can not write to badblocks file \"%s\": %s 
\n",
+                       op->bbname, strerror(errno));
+               return;
+       }
        fprintf(bbfile, "%s\n", fmt_int(0, 0, 1, block, "", "", 0));
        fclose(bbfile);
 }
@@ -1339,14 +1365,14 @@
 }
 
 
+/** Copy permissions, return 0 on success, negative on error */
 int copyperm(int ifd, int ofd)
 {
-       int err; 
-       mode_t fmode;
        struct stat stbuf;
-       err = fstat(ifd, &stbuf);
+       mode_t fmode;
+       int err = fstat(ifd, &stbuf);
        if (err)
-               return -err;
+               return err;
        fmode = stbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | 
S_ISGID | S_ISVTX);
        err = fchown(ofd, stbuf.st_uid, stbuf.st_gid);
        /* Drop setuid bits if we failed to copy the owner */
@@ -1358,15 +1384,12 @@
 
 int copyperm_err(int ifd, int ofd, const char* inm, const char* onm, char 
fatal)
 {
+       const enum ddrlog_t wlevel = fatal? FATAL: WARN;
        int err = copyperm(ifd, ofd);
        if (!err)
                return 0;
-       if (!fatal) {
-               fplog(stderr, WARN, "Setting permissions on %s failed: %s\n", 
err>0? onm: inm, strerror(errno));
-               return 0;
-       }
-       fplog(stderr, FATAL, "Setting permissions on %s failed: %s\n", err>0? 
onm: inm, strerror(errno));
-       return err>0? err: -err;
+       fplog(stderr, wlevel, "Setting permissions on %s failed: %s\n", err>0? 
onm: inm, strerror(errno));
+       return fatal? -err: 0;
 }
 
 /** Copy xattrs */
@@ -1392,13 +1415,21 @@
        }
        int offs;
        unsigned char* extrabuf = (unsigned char*)malloc(4096);
-       assert(extrabuf);
-       int ebufall = 4096;
+       if (!extrabuf) {
+               fplog(stderr, WARN, "Can't allocate extra buffer of len 4096 
for attrs\n");
+               free(attrs);
+               return -1;
+       }
+       ssize_t ebufall = 4096;
        for (offs = 0; offs < aln; offs += 1+strlen(attrs+offs)) {
                ssize_t itln = getxattr(inm, attrs+offs, NULL, 0);
-               if (ebufall && itln > ebufall) {
+               if (itln > ebufall) {
                        extrabuf = (unsigned char*)realloc(extrabuf, itln);
-                       assert(extrabuf);
+                       if (!extrabuf) {
+                               fplog(stderr, WARN, "Can't allocate extra 
buffer of len %i for attrs\n", itln);
+                               --errs;
+                               continue;
+                       }
                        ebufall = itln;
                }
                itln = getxattr(inm, attrs+offs, extrabuf, itln);
@@ -1414,8 +1445,7 @@
                fplog(stderr, DEBUG, "Copied attr %s (%i bytes)\n", attrs+offs, 
itln);
                ++copied;
        }
-       if (ebufall)
-               free(extrabuf);
+       free(extrabuf);
        free(attrs);
        return errs? errs: copied;
 }
@@ -1510,8 +1540,15 @@
                /* Make sure, the output file is expanded to the last (first) 
position
                 * FIXME: 0 byte writes do NOT expand file -- mayexpandfile() 
will
                 * take care of that. */
-               if (!op->avoidwrite) 
+               if (!op->avoidwrite) {
                        rc = pwrite(fd, fst->buf, 0, fst->opos);
+                       if (rc == -1) {
+                               fplog(stderr, WARN, "pwrite0 %s (%skiB): %s!\n",
+                                     nm, fmt_kiB(fst->opos, !nocol), 
strerror(errno));
+                               ++err;
+                               errno = 0;
+                       }
+               }
                rc = fsync(fd);
                if (rc && !chr) {
                        fplog(stderr, WARN, "fsync %s (%skiB): %s!\n",
@@ -3097,6 +3134,7 @@
        const char* ibase = mybasename(inm);
        const int dlen = strlen(dir) + (dirsep>0? 1: dirsep);
        char* ret = (char*)malloc(dlen + strlen(inm) + 1);
+       assert(ret);
        strcpy(ret, dir);
        if (dirsep > 0) {
                ret[dlen-1] = dirsep;
@@ -3528,7 +3566,7 @@
                if (op->init_opos == (loff_t)-INT_MAX) 
                        op->init_opos = op->init_ipos;
                /* if explicitly set to zero, assume end of _existing_ file */
-               if (op->init_opos == 0) {
+               else if (op->init_opos == 0) {
                        op->init_opos = lseek64(fst->odes, 0, SEEK_END);
                        if (op->init_opos == (loff_t)-1) {
                                fplog(stderr, FATAL, "could not seek to end of 
file %s!\n", op->oname);
@@ -3542,7 +3580,7 @@
                        if (op->verbose) 
                                fprintf(stderr, DDR_INFO "opos set to: %skiB\n",
                                        fmt_kiB(op->init_opos, !nocol));
-               }
+               } /* else FIXME: Do we want to correct output pos by ilen ? */
        }
 
        /* if op->init_opos not set, assume same position */
@@ -3552,12 +3590,49 @@
        if (fst->identical) {
                fplog(stderr, WARN, "infile and outfile are identical!\n");
                if (op->init_opos > op->init_ipos && !op->reverse && 
!op->force) {
-                       fplog(stderr, WARN, "turned on reverse, as ipos < 
opos!\n");
-                       op->reverse = 1;
+                       /* Bug up to and incl. 1.99.22: Need to also change 
starting positions! */
+                       const loff_t ilen = file_len(fst->ides, &fst->i_chr, 
&fst->o_blk, op->iname, op->sparse);
+                       /* If opos > ipos BUT no overlap, we don't need reverse 
*/
+                       if (!op->maxxfer && ilen) {
+                               op->maxxfer = ilen - op->init_ipos;
+                               fplog(stderr, INFO, "Limit copy len to current 
len %skiB\n", fmt_kiB(op->maxxfer, !nocol));
+                       }
+                       if (op->maxxfer && op->init_ipos + op->maxxfer <= 
op->init_opos)
+                               fplog(stderr, INFO, "No overlap, no need to 
reverse\n");
+                       else {
+                               op->reverse = 1;
+                               fplog(stderr, WARN, "turned on reverse, as ipos 
< opos with overlap!\n");
+                               if (op->maxxfer) {
+                                       op->init_ipos += op->maxxfer;
+                                       op->init_opos += op->maxxfer;
+                               } else {
+                                       fplog(stderr, FATAL, "input file len 
unknown, can not reverse copy!\n");
+                                       perror("dd_rescue"); cleanup(1); 
exit(19);
+                               }
+                       }
+                       /* Repeat earlier check */
+                       if (op->reverse && plug_no_seek) {
+                               fplog(stderr, FATAL, "Plugins currently don't 
handle reverse\n");
+                               //unload_plugins();
+                               cleanup(1);
+                               exit(13);
+                       }
                }
                if (op->init_opos < op->init_ipos && op->reverse && !op->force) 
{
-                       fplog(stderr, WARN, "turned off reverse, as opos < 
ipos!\n");
-                       op->reverse = 0;
+                       /* Bug up to and incl. 1.99.22: Need to also change 
starting positions! */
+                       /* FIXME: We should detect the overlap and only adjust 
if needed. */
+                       if (!op->maxxfer || op->maxxfer > op->init_opos) {
+                               fplog(stderr, WARN, "set max xfer to output pos 
%skiB\n", fmt_kiB(op->init_opos, !nocol));
+                               op->maxxfer = op->init_opos;
+                       }
+                       if (op->maxxfer && op->init_ipos - op->maxxfer >= 
op->init_opos) {
+                               fplog(stderr, INFO, "No overlap, no need to 
clear reverse\n");
+                       } else {
+                               op->reverse = 0;
+                               fplog(stderr, WARN, "turned off reverse, as 
opos < ipos with overlap!\n");
+                               op->init_ipos -= op->maxxfer;
+                               op->init_opos -= op->maxxfer;
+                       }
                }
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/ddr_plugin.h 
new/dd_rescue-1.99.24/ddr_plugin.h
--- old/dd_rescue-1.99.22/ddr_plugin.h  2025-01-19 17:47:01.328706656 +0100
+++ new/dd_rescue-1.99.24/ddr_plugin.h  2026-08-07 08:14:51.000000000 +0200
@@ -220,6 +220,10 @@
        return ptr;
 }
 
+#if defined(__GNUC__) && __GNUC__ >= 12
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
+#endif
 static inline
 unsigned char* slack_alloc(const size_t ln, const unsigned int pre, const 
unsigned int post,
                           const cleartp clear, const ddr_plugin_t *plug, const 
int seq)
@@ -237,6 +241,9 @@
        unsigned char *ptr = (unsigned char*)realloc(old-pre, ln+pre+post);
        return _slack_process(ptr, ln, pre, post, clear, *plug, seq);
 }
+#if defined(__GNUC__) && __GNUC__ >= 12
+#pragma GCC diagnostic pop
+#endif
 
 static inline
 void slack_free(unsigned char *ptr, const unsigned int pre)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/find_nonzero.c 
new/dd_rescue-1.99.24/find_nonzero.c
--- old/dd_rescue-1.99.22/find_nonzero.c        2025-01-07 02:57:30.396367447 
+0100
+++ new/dd_rescue-1.99.24/find_nonzero.c        2026-08-07 08:14:51.000000000 
+0200
@@ -125,6 +125,7 @@
        size_t ln = 0;
        double tdiff;
        int scale = 16;
+       assert(obuf);
        detect_cpu_cap();
 
        printf("Using extensions: %s\n", OPT_STR);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/frandom.c 
new/dd_rescue-1.99.24/frandom.c
--- old/dd_rescue-1.99.22/frandom.c     2024-09-21 22:19:30.937030295 +0200
+++ new/dd_rescue-1.99.24/frandom.c     2026-08-07 08:14:51.000000000 +0200
@@ -126,7 +126,6 @@
        struct frandom_state *state;
 
        state = (struct frandom_state *)malloc(sizeof(struct frandom_state));
-       //assert(state);
        if (!state)
                abort();
                //return NULL;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/fuzz_lzo.c 
new/dd_rescue-1.99.24/fuzz_lzo.c
--- old/dd_rescue-1.99.22/fuzz_lzo.c    2023-02-23 22:51:27.361221369 +0100
+++ new/dd_rescue-1.99.24/fuzz_lzo.c    2026-08-07 08:14:51.000000000 +0200
@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <utime.h>
 #include <string.h>
+#include <assert.h>
 #include <netinet/in.h>
 //#include <sys/mman.h>
 #include "list.h"
@@ -228,6 +229,9 @@
        unsigned char *dbuf = (unsigned char*)malloc(blksz);
        unsigned char *cbuf = (unsigned char*)malloc(CBFLEN); 
        unsigned char *wmem = (unsigned char*)malloc(LZO1X_1_MEM_COMPRESS);
+       assert(dbuf);
+       assert(cbuf);
+       assert(wmem);
        do {
                rd = read(ifd, dbuf, blksz);
                if (!rd)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/libddr_crypt.c 
new/dd_rescue-1.99.24/libddr_crypt.c
--- old/dd_rescue-1.99.22/libddr_crypt.c        2025-02-16 19:49:11.559820366 
+0100
+++ new/dd_rescue-1.99.24/libddr_crypt.c        2026-08-07 08:14:51.000000000 
+0200
@@ -185,6 +185,7 @@
 {
        int err = 0;
        crypt_state *state = (crypt_state*)malloc(sizeof(crypt_state));
+       assert(state);
        *stat = (void*)state;
        memset(state, 0, sizeof(crypt_state));
        state->seq = seq;
@@ -949,14 +950,17 @@
 #ifdef HAVE_XATTR
        if (state->sxattr && !state->salt_xattr_name) {
                state->salt_xattr_name = malloc(32);
+               assert(state->salt_xattr_name);
                snprintf(state->salt_xattr_name, 32, "user.salt.%s", 
state->alg->name);
        }
        if (state->kxattr && !state->key_xattr_name) {
                state->key_xattr_name = malloc(32);
+               assert(state->key_xattr_name);
                snprintf(state->key_xattr_name, 32, "user.key.%s", 
state->alg->name);
        }
        if (state->ixattr && !state->iv_xattr_name) {
                state->iv_xattr_name = malloc(32);
+               assert(state->iv_xattr_name);
                snprintf(state->iv_xattr_name, 32, "user.iv.%s", 
state->alg->name);
        }
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/libddr_hash.c 
new/dd_rescue-1.99.24/libddr_hash.c
--- old/dd_rescue-1.99.22/libddr_hash.c 2025-01-20 12:30:43.814875946 +0100
+++ new/dd_rescue-1.99.24/libddr_hash.c 2026-10-09 13:55:44.000000000 +0200
@@ -363,6 +363,7 @@
                state->fname = opt->iname;
        else {
                char* nnm = 
(char*)malloc(strlen(opt->iname)+strlen(opt->oname)+3);
+               assert(nnm);
                strcpy(nnm, opt->iname);
                strcat(nnm, "->");
                strcat(nnm, opt->oname);
@@ -630,9 +631,10 @@
                }
        }
        if (strcmp(cks, res)) {
-               FPLOG(WARN, "Hash from chksum file %s for %s does not match\n", 
state->chkfnm, name);
-               FPLOG(WARN, "comp %s, read %s\n", res, cks);
-               return -EBADF;
+               FPLOG(FATAL, "Hash from chksum file %s for %s does not 
match\n", state->chkfnm, name);
+               FPLOG(FATAL, "expect %s, calc %s\n", res, cks);
+               /* -EBADF ? */
+               return -ERANGE;
        }
        return 0;
 }
@@ -689,6 +691,7 @@
        char chksum[144];
        ssize_t itln = getxattr(name, state->xattr_name, chksum, 144);
        const int rln = strlen(res);
+       chksum[143] = 0;
        if (itln <= 0) {
                if (state->xfallback) {
                        int err = get_chks(state->chkfnm, name, chksum, rln);
@@ -701,16 +704,20 @@
                                        return -ENOENT;
                                }
                        } else if (strcmp(chksum, res)) {
-                               FPLOG(WARN, "Hash from %s for %s does not 
match\n", xatstr, name);
-                               return -EBADF;
+                               FPLOG(FATAL, "Hash from %s for %s does not 
match\n", xatstr, name);
+                               FPLOG(FATAL, "expect %s, calc %s\n", res, 
chksum);
+                               /* -EBADF ? */
+                               return -ERANGE;
                        }
                } else {
                        FPLOG(WARN, "Hash could not be read from xattr of 
%s\n", name);
                        return -ENOENT;
                }
        } else if (itln < rln || memcmp(res, chksum, rln)) {
-               FPLOG(WARN, "Hash from xattr of %s does not match\n", name);
-               return -EBADF;
+               FPLOG(FATAL, "Hash from xattr of %s does not match\n", name);
+               FPLOG(FATAL, "expect %s, calc %s\n", res, chksum);
+               /* -EBADF ? */
+               return -ERANGE;
        }
        if (!state->opts->quiet || state->debug)
                FPLOG(INFO, "Successfully validated hash from %s for %s\n", 
xatstr, name);
@@ -774,7 +781,7 @@
        if (state->set_xattr)
                err += write_xattr(state, res);
 #endif
-       return -err;
+       return err;
 }
 
 static char _kout_buf[2049];
@@ -831,6 +838,7 @@
        klen = atol(next)/8;
 
        key = (unsigned char*)malloc(klen);
+       assert(key);
 
        err = pbkdf2(halg, (unsigned char*)pwd, strlen(pwd), 
                         (unsigned char*)salt, strlen(salt),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/libddr_lzma.c 
new/dd_rescue-1.99.24/libddr_lzma.c
--- old/dd_rescue-1.99.22/libddr_lzma.c 2025-01-20 01:36:08.592070346 +0100
+++ new/dd_rescue-1.99.24/libddr_lzma.c 2026-08-07 08:14:51.000000000 +0200
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <time.h>
+#include <assert.h>
 #ifdef HAVE_LZMA_H     // Avoid breaking on dependency generation
 #include <lzma.h>
 #endif
@@ -144,6 +145,7 @@
 int lzma_plug_init(void **stat, char* param, int seq, const opt_t *opt)
 {
        lzma_state *state = (lzma_state *)malloc(sizeof(lzma_state));
+       assert(state);
        if (!state) {
                FPLOG_(-1, FATAL, "allocation of %zd bytes failed: %s\n", 
sizeof(lzma_state), strerror(errno));
                return -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/libddr_lzo.c 
new/dd_rescue-1.99.24/libddr_lzo.c
--- old/dd_rescue-1.99.22/libddr_lzo.c  2025-01-20 15:32:33.061336447 +0100
+++ new/dd_rescue-1.99.24/libddr_lzo.c  2026-08-07 08:14:51.000000000 +0200
@@ -387,6 +387,7 @@
 {
        int err = 0;
        lzo_state *state = (lzo_state*)malloc(sizeof(lzo_state));
+       assert(state);
        *stat = (void*)state;
        if (!state) {
                FPLOG(FATAL, "can't allocate %i bytes\n", sizeof(lzo_state));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/libddr_null.c 
new/dd_rescue-1.99.24/libddr_null.c
--- old/dd_rescue-1.99.22/libddr_null.c 2025-01-19 18:00:21.439495249 +0100
+++ new/dd_rescue-1.99.24/libddr_null.c 2026-08-07 08:14:51.000000000 +0200
@@ -38,6 +38,7 @@
 int null_plug_init(void **stat, char* param, int seq, const opt_t *opt)
 {
        null_state *state = (null_state*)malloc(sizeof(null_state));
+       assert(state);
        *stat = (void*)state;
        memset(state, 0, sizeof(null_state));
        state->seq = seq;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/md5.c new/dd_rescue-1.99.24/md5.c
--- old/dd_rescue-1.99.22/md5.c 2024-12-29 18:52:25.111164535 +0100
+++ new/dd_rescue-1.99.24/md5.c 2026-08-07 08:14:51.000000000 +0200
@@ -255,6 +255,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <assert.h>
 #define BUFSIZE 65536
 int main(int argc, char **argv)
 {
@@ -268,6 +269,7 @@
 
        uint8_t *obf = (uint8_t *)malloc(BUFSIZE + 128);
        uint8_t *bf = obf;
+       assert(obf);
 #if defined(HAVE___BUILTIN_PREFETCH) && !defined(NO_ALIGN)
        bf += 63;
        bf -= ((unsigned long)bf % 64);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/ossl_pbkdf2.c 
new/dd_rescue-1.99.24/ossl_pbkdf2.c
--- old/dd_rescue-1.99.22/ossl_pbkdf2.c 2022-07-26 16:59:04.097614105 +0200
+++ new/dd_rescue-1.99.24/ossl_pbkdf2.c 2026-08-07 08:14:51.000000000 +0200
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdio.h>
+#include <assert.h>
 
 void PBKDF2_HMAC_SHA512(const char* pass, const unsigned char* salt, int32_t 
iterations, uint32_t outputBytes, char* hexResult) 
 { 
@@ -49,6 +50,7 @@
                usage();
        int olen = atol(argv[4])/8;
        char* obuf = (char*)malloc(1+2*olen);
+       assert(obuf);
        OPENSSL_init();
        PBKDF2_HMAC_SHA1(argv[1], (unsigned char*)argv[2], atol(argv[3]), olen, 
obuf);
        printf("PBKDF2(SHA1  , ...) = %s\n", obuf);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/pbkdf2.c 
new/dd_rescue-1.99.24/pbkdf2.c
--- old/dd_rescue-1.99.22/pbkdf2.c      2021-04-14 10:23:02.000000000 +0200
+++ new/dd_rescue-1.99.24/pbkdf2.c      2026-08-07 08:14:51.000000000 +0200
@@ -115,6 +115,8 @@
        const unsigned int bflen = MAX((unsigned)slen+4, hlen)+hash->blksz;
        unsigned char* buf = (unsigned char*)malloc(bflen);
        unsigned char* khash = (unsigned char*)malloc(khlen);
+       assert(buf);
+       assert(khash);
        memset(buf, 0, bflen); memset(khash, 0, khlen);
        if ((unsigned)plen > hlen) {
                hash_t hv;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/pbkdf_ossl.c 
new/dd_rescue-1.99.24/pbkdf_ossl.c
--- old/dd_rescue-1.99.22/pbkdf_ossl.c  2021-04-14 10:23:02.000000000 +0200
+++ new/dd_rescue-1.99.24/pbkdf_ossl.c  2026-08-07 08:14:51.000000000 +0200
@@ -38,6 +38,7 @@
        unsigned char* hbuf = malloc(hash->hashln+plen+slen);
        unsigned int off = 0;
        unsigned cnt = 0;
+       assert(hbuf);
        assert(iter == 1);
        hash_t hv;
        while (off < klen+ivlen) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/sha1.c new/dd_rescue-1.99.24/sha1.c
--- old/dd_rescue-1.99.22/sha1.c        2024-12-29 18:52:25.111164535 +0100
+++ new/dd_rescue-1.99.24/sha1.c        2026-08-07 08:14:51.000000000 +0200
@@ -236,6 +236,7 @@
 
        uint8_t *obf = (uint8_t *)malloc(BUFSIZE + 128);
        uint8_t *bf = obf;
+       assert(obf);
 #if defined(HAVE___BUILTIN_PREFETCH) && !defined(NO_ALIGN)
        bf += 63;
        bf -= ((unsigned long)bf % 64);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/sha256.c 
new/dd_rescue-1.99.24/sha256.c
--- old/dd_rescue-1.99.22/sha256.c      2024-12-29 18:52:25.111164535 +0100
+++ new/dd_rescue-1.99.24/sha256.c      2026-08-07 08:14:51.000000000 +0200
@@ -519,6 +519,7 @@
 
        uint8_t *obf = (uint8_t *)malloc(BUFSIZE + 128);
        uint8_t *bf = obf;
+       assert(obf);
 #if defined(HAVE___BUILTIN_PREFETCH) && !defined(NO_ALIGN)
        bf += 63;
        bf -= ((unsigned long)bf % 64);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/sha512.c 
new/dd_rescue-1.99.24/sha512.c
--- old/dd_rescue-1.99.22/sha512.c      2024-12-29 18:52:25.111164535 +0100
+++ new/dd_rescue-1.99.24/sha512.c      2026-08-07 08:14:51.000000000 +0200
@@ -340,8 +340,9 @@
        }
 
        uint8_t *obf = (uint8_t *)malloc(BUFSIZE + 256);
-       //memset(obf, 0, BUFSIZE+256);
        uint8_t *bf = obf;
+       assert(obf);
+       //memset(obf, 0, BUFSIZE+256);
 #if defined(HAVE___BUILTIN_PREFETCH) && !defined(NO_ALIGN)
        bf += 127;
        bf -= ((unsigned long)bf % 128);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.22/test_crypt.sh 
new/dd_rescue-1.99.24/test_crypt.sh
--- old/dd_rescue-1.99.22/test_crypt.sh 2025-01-06 00:48:44.772889058 +0100
+++ new/dd_rescue-1.99.24/test_crypt.sh 2026-10-08 22:56:20.000000000 +0200
@@ -125,7 +125,7 @@
 #exit 1
 
 # Chain with lzo, hash (all)
-if test -n "$HAVE_LZO"; then
+if test -n "$HAVE_LZO" -a "$HAVE_LZO" != "0"; then
 echo "# *** Plugin chains ... ***"
 rm -f CHECHSUMS.*
 SHA256SUM=`type -p sha256sum`
@@ -147,7 +147,7 @@
 fi
 
 # Chain with lzo, hash sha512 (all)
-if test -n "$HAVE_LZO"; then
+if test -n "$HAVE_LZO" -a "$HAVE_LZO" != "0"; then
 echo "# *** Plugin chains ... ***"
 SHA512SUM=`type -p sha512sum`
 run_ddr -pqt -L 
./libddr_hash.so=sha512:outnm=,./libddr_lzo.so=compr,./libddr_hash.so=sha512:output,./libddr_crypt.so=enc:AES192-CTR:keygen:ivgen:weakrnd:keysfile:ivsfile,./libddr_hash.so=sha512:outnm=
 dd_rescue3 dd_rescue3.enc || exit 1

Reply via email to