5
0
mirror of git://git.proxmox.com/git/proxmox-backup.git synced 2025-03-11 16:58:32 +03:00

datastore: data blob: allow checking for zstd internal buffer-to-small error

We want to check the error code of zstd not to be 'Destination buffer
to small' (dstSize_tooSmall),  but currently there is no practical API
that is also public. So we introduce a helper that uses the internal
logic of zstd to determine the error.

Since this is not guaranteed to be a stable api, add a test for that
so we catch that error early on build. This should be fine, as long as
the zstd behavior only changes with e.g. major debian upgrades, which
is normally the only time where the zstd version is updated.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
 [ TL: re-order fn, rename test and reword comments ]
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Dominik Csapak 2024-08-05 11:24:12 +02:00 committed by Thomas Lamprecht
parent 69b8b4b02f
commit e1d92bce57
4 changed files with 32 additions and 1 deletions

View File

@ -158,6 +158,7 @@ url = "2.1"
walkdir = "2"
xdg = "2.2"
zstd = { version = "0.12", features = [ "bindgen" ] }
zstd-safe = "6.0"
[dependencies]
anyhow.workspace = true

1
debian/control vendored
View File

@ -145,6 +145,7 @@ Build-Depends: bash-completion,
librust-xdg-2+default-dev (>= 2.2-~~),
librust-zstd-0.12+bindgen-dev,
librust-zstd-0.12+default-dev,
librust-zstd-safe-6-dev,
libsgutils2-dev,
libstd-rust-dev,
libsystemd-dev (>= 246-~~),

View File

@ -23,6 +23,7 @@ tokio = { workspace = true, features = [] }
tracing.workspace = true
walkdir.workspace = true
zstd.workspace = true
zstd-safe.workspace = true
pathpatterns.workspace = true
pxar.workspace = true

View File

@ -563,11 +563,23 @@ impl<'a, 'b> DataChunkBuilder<'a, 'b> {
}
}
/// Check if the error code returned by `zstd_safe::compress`, or anything else that does FFI calls
/// into zstd code, was `70` 'Destination buffer is too small' by subtracting the error code from
/// `0` (with underflow), see `ERR_getErrorCode` in
/// https://github.com/facebook/zstd/blob/dev/lib/common/error_private.h
///
/// There is a test below to ensure we catch any change in the interface or internal value.
fn zstd_error_is_target_too_small(err: usize) -> bool {
let (real_code, _) = 0usize.overflowing_sub(err);
// see ZSTD_ErrorCode in https://github.com/facebook/zstd/blob/dev/lib/zstd_errors.h
real_code == 70 // ZSTD_error_dstSize_tooSmall
}
#[cfg(test)]
mod test {
use pbs_tools::crypt_config::CryptConfig;
use super::DataChunkBuilder;
use super::{zstd_error_is_target_too_small, DataChunkBuilder};
const TEST_DATA_LEN: usize = 50;
@ -640,4 +652,20 @@ mod test {
.expect("cannot decode encrypted, compressed chunk");
assert_eq!(data, data_decoded);
}
#[test]
/// test for the error code internal logic of zstd so we catch any interface/value changes on
/// (package) compile time
fn zstd_assert_dst_size_to_small_error_code_abi() {
let data = &build_test_data();
let mut target = Vec::new();
match zstd_safe::compress(&mut target, data, 1) {
Ok(_) => panic!("unexpected success with zero-sized buffer"),
Err(err) => {
if !zstd_error_is_target_too_small(err) {
panic!("unexpected error code {err}, check test validity and zstd for changes!");
}
}
}
}
}