Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a57a504
Decouple liblzma-sys backend from bindgen
youknowone Apr 13, 2026
c6236a1
trim
youknowone Apr 13, 2026
5142a3d
Refine xz internals and restore systest perf builds
youknowone Apr 13, 2026
1f964de
Tidy trivial c2rust naming remnants
youknowone Apr 13, 2026
3627f85
Tidy remaining low-risk c2rust naming
youknowone Apr 13, 2026
1ebdc7b
Use ctest 0.5.1 raw identifier support
youknowone Apr 13, 2026
a93e21b
Reduce mutable statics and narrow unsafe helpers
youknowone Apr 13, 2026
d8d77f1
revert crc64
youknowone Apr 14, 2026
2d7323e
ifix
youknowone Apr 14, 2026
19e4fe3
cleanup
youknowone Apr 14, 2026
ce93d55
Reduce internal panic paths
youknowone Apr 16, 2026
0314bc7
Refine LZMA hot paths and backend comparison tooling
youknowone Apr 16, 2026
834e3fd
Tune performance probes and hot paths
youknowone Apr 17, 2026
c4b047d
Trim hot-path function-pointer checks
youknowone Apr 17, 2026
2211802
remove redundant
youknowone Apr 17, 2026
dc080a9
edition 2024
youknowone Apr 17, 2026
1c627e0
xz 5.8.3
youknowone Apr 18, 2026
146611d
Optino<fn>
youknowone Apr 18, 2026
e8a96e6
Replace c2rust state hashes with named control flow
youknowone Apr 18, 2026
b36bdd0
Refine allocator defaults and optimum helper flow
youknowone Apr 18, 2026
d1ae9b8
refine
youknowone Apr 19, 2026
db7ed70
Revert top-level src changes to origin
youknowone Apr 20, 2026
1a94603
1.88
youknowone Apr 20, 2026
674511a
fix systest
youknowone Apr 20, 2026
e944c6f
let-else
youknowone Apr 20, 2026
7a41ac9
Restore cold literal-after helpers in optimum encoder
youknowone Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ wasm-bindgen-test = "0.3"
default = ["xz"]
xz = ["dep:xz"]
xz-sys = ["dep:xz-sys"]
liblzma-sys = ["dep:liblzma-sys", "liblzma-sys/bindgen"]
liblzma-sys = ["dep:liblzma-sys"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Cargo, when the same crate appears in [dependencies]and[dev-dependencies], are features unified for benches/examples/tests, and do default features from the dev-dependency stay enabled?

💡 Result:

Yes, when the same crate appears in both [dependencies] and [dev-dependencies], Cargo unifies the features for builds that include dev-dependencies (benches, examples, tests). This uses the union of features specified in both sections. Default features from the dev-dependency declaration remain enabled unless explicitly disabled there (via default-features = false). For normal builds (cargo build on lib/bin), only [dependencies] features apply (dev-deps ignored). This behavior depends on the feature resolver version (default "2" for edition 2021+, controlled by top-level resolver field). Resolver v2 avoids unwanted unification but includes dev-dep features when building dev targets like tests/examples/benches. Example from docs: [dependencies] serde = {version = "1.0", default-features = false} [dev-dependencies] serde = {version = "1.0", features = ["std"]} - cargo build: serde without features (defaults off). - cargo test: serde with "std" (union, defaults from dev-dep enabled since not disabled).

Citations:


🏁 Script executed:

# Check the structure of Cargo.toml, particularly around the lines mentioned
sed -n '20,60p' Cargo.toml | cat -n

Repository: youknowone/xz-rs

Length of output: 1680


liblzma-sys still enables bindgen for dev targets.

Line 45 defines a target-specific dev-dependency liblzma-sys = { path = "liblzma-sys" } without default-features = false. When benches/examples/tests are built with the liblzma-sys feature, Cargo unifies features across dependencies and dev-dependencies, re-enabling the default bindgen feature from the dev-dependency. This defeats the goal of disabling it at Line 25 and keeps the libclang requirement around for those builds.

♻️ Proposed fix
 [target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
 xz-sys = { path = "xz-sys" }
-liblzma-sys = { path = "liblzma-sys" }
+liblzma-sys = { path = "liblzma-sys", default-features = false }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Cargo.toml` at line 54, The dev-dependency entry for liblzma-sys still pulls
in its default features (re-enabling bindgen); update the liblzma-sys dependency
declarations so they set default-features = false (both the target-specific
dev-dependency and the liblzma-sys = ["dep:liblzma-sys"] mapping) to prevent the
bindgen feature from being activated for benches/examples/tests; look for the
liblzma-sys entries and add default-features = false (and adjust to a table form
if needed) to ensure the bindgen feature stays disabled.

static = ["liblzma-sys?/static"]
parallel = ["xz-sys?/parallel", "liblzma-sys?/parallel", "num_cpus"]
bindgen = ["liblzma-sys?/bindgen"] # only affects liblzma-sys
Expand Down
35 changes: 24 additions & 11 deletions benches/backend_comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@ compile_error!("backend_comparison bench requires `xz`, `xz-sys`, or `liblzma-sy
#[cfg(feature = "liblzma-sys")]
use liblzma_sys::{
lzma_crc32, lzma_crc64, lzma_easy_buffer_encode, lzma_stream_buffer_bound,
lzma_stream_buffer_decode, LZMA_CHECK_CRC64,
lzma_stream_buffer_decode, LZMA_CHECK_CRC64, LZMA_OK,
};
#[cfg(feature = "xz")]
use xz::check::{crc32_fast::lzma_crc32, crc64_fast::lzma_crc64};
#[cfg(feature = "xz")]
use xz::common::{
easy_buffer_encoder::lzma_easy_buffer_encode, stream_buffer_decoder::lzma_stream_buffer_decode,
stream_buffer_encoder::lzma_stream_buffer_bound,
use xz::{
check::{crc32_fast::lzma_crc32, crc64_fast::lzma_crc64},
common::{
easy_buffer_encoder::lzma_easy_buffer_encode,
stream_buffer_decoder::lzma_stream_buffer_decode,
stream_buffer_encoder::lzma_stream_buffer_bound,
},
types::{LZMA_CHECK_CRC64, LZMA_OK},
};
#[cfg(feature = "xz")]
use xz::types::LZMA_CHECK_CRC64;
#[cfg(feature = "xz-sys")]
use xz_sys::{
lzma_crc32, lzma_crc64, lzma_easy_buffer_encode, lzma_stream_buffer_bound,
lzma_stream_buffer_decode, LZMA_CHECK_CRC64,
lzma_stream_buffer_decode, LZMA_CHECK_CRC64, LZMA_OK,
};

#[cfg(feature = "xz")]
Expand All @@ -56,7 +57,7 @@ unsafe fn backend_encode(input: &[u8]) -> Vec<u8> {
let bound = lzma_stream_buffer_bound(input.len());
let mut out = vec![0u8; bound];
let mut out_pos: usize = 0;
lzma_easy_buffer_encode(
let ret = lzma_easy_buffer_encode(
6,
LZMA_CHECK_CRC64,
ptr::null(),
Expand All @@ -66,6 +67,7 @@ unsafe fn backend_encode(input: &[u8]) -> Vec<u8> {
&mut out_pos,
out.len(),
);
assert_eq!(ret, LZMA_OK, "{BACKEND_NAME} encode failed with {ret}");
out.truncate(out_pos);
out
}
Expand All @@ -75,7 +77,7 @@ unsafe fn backend_decode(compressed: &[u8], out_size: usize) -> Vec<u8> {
let mut memlimit = u64::MAX;
let mut in_pos = 0usize;
let mut out_pos = 0usize;
lzma_stream_buffer_decode(
let ret = lzma_stream_buffer_decode(
&mut memlimit,
0,
ptr::null(),
Expand All @@ -86,6 +88,17 @@ unsafe fn backend_decode(compressed: &[u8], out_size: usize) -> Vec<u8> {
&mut out_pos,
out.len(),
);
assert_eq!(ret, LZMA_OK, "{BACKEND_NAME} decode failed with {ret}");
assert_eq!(
in_pos,
compressed.len(),
"{BACKEND_NAME} decode left trailing input: consumed {in_pos} of {} bytes",
compressed.len()
);
assert_eq!(
out_pos, out_size,
"{BACKEND_NAME} decode produced {out_pos} bytes, expected {out_size}"
);
out.truncate(out_pos);
out
}
Expand Down
26 changes: 22 additions & 4 deletions docs/performance-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ Use `hyperfine` to compare end-to-end wall clock time of the deterministic root
scripts/compare_backends.sh --runs 10 --warmup 2
```

For the full no-regression gate across the standard root, systest, focused, and
API workloads, use the trimmed comparison wrapper:

```bash
scripts/compare_all_trimmed.sh
```

It measures each Rust/C pair five times, discards the fastest and slowest runs,
averages the remaining runs, and exits with failure if Rust is slower than C
after trimming. Reports are written under `target/perf-results/trimmed/`.

This writes:

- `target/perf-results/root-tests.json`
Expand All @@ -47,14 +58,14 @@ The root bundle intentionally skips QuickCheck-based unit tests because they gen

## 3. Compare focused workloads

Use `perf-probe`, a small standalone binary crate that links exactly one backend at a time. The comparison scripts use the direct `xz` backend by default; `xz-sys` remains available for ABI-shell checks.
Use `perf-probe`, a small standalone binary crate that links exactly one backend at a time. `scripts/compare_workloads.sh` compares all three backends in separate processes: direct `xz`, `xz-sys`, and vendored C `liblzma-sys`.

Examples:

```bash
scripts/compare_workloads.sh encode --input-kind random --size 1048576 --iters 20 --warmup 3
scripts/compare_workloads.sh decode --input-kind random --size 1048576 --iters 50 --warmup 5
scripts/compare_workloads.sh size --input-kind random --size 1048576 --iters 400 --warmup 40
scripts/compare_workloads.sh size --input-kind random --size 1048576 --iters 10000000 --warmup 1000000
scripts/compare_workloads.sh crc64 --size 16777216 --iters 400 --warmup 20
scripts/compare_workloads.sh crc64 --size 1048576 --chunk-size 16 --iters 400 --warmup 40
```
Expand All @@ -63,15 +74,17 @@ This writes workload-specific `hyperfine` reports under `target/perf-results/`.

For tiny inputs, increase `--iters` until one benchmarked command takes at least around a
second. Otherwise process startup noise can dominate the comparison even when the actual
backend work is near parity.
backend work is near parity. The `size` workload is especially small, so it needs millions
of in-process iterations; the comparison scripts also pre-generate its compressed input so
the one-time encode setup doesn't hide the `uncompressed_size()` path.

There is still a criterion bench in [`benches/backend_comparison.rs`](../benches/backend_comparison.rs), but it now measures one backend per run. Use it only with exactly one backend feature enabled.

For high-level API regressions, compare the root crate against the upstream XZ corpus:

```bash
scripts/compare_api_workloads.sh standard-files --mode all --iters 200 --warmup 20
scripts/compare_api_workloads.sh standard-files --mode good --iters 400 --warmup 40
scripts/compare_api_workloads.sh standard-files --mode good --iters 1000 --warmup 100
scripts/compare_api_workloads.sh standard-files --mode good --name-pattern delta --iters 400 --warmup 40
scripts/compare_api_workloads.sh qc --mode both --cases 128 --max-size 4096 --iters 200 --warmup 20
scripts/compare_api_workloads.sh bufread-trailing --mode both --input-size 1024 --trailing-size 123 --iters 1000 --warmup 100
Expand All @@ -82,6 +95,11 @@ This uses [`examples/standard_files_probe.rs`](../examples/standard_files_probe.
- `target/perf-results/api-standard-files.json`
- `target/perf-results/api-standard-files.md`

The `good` subset is small enough that a few hundred iterations can still leave
too much wall-clock noise. Prefer around `--iters 1000 --warmup 100` when
comparing `--mode good` so the in-process work dominates process scheduling
variance.

The `qc` workload uses [`examples/qc_probe.rs`](../examples/qc_probe.rs) to reproduce the
small-input repeated round-trip pattern from the root crate tests. This is useful when
overall regressions show up in `root-tests` even though large encode/decode probes look
Expand Down
13 changes: 13 additions & 0 deletions liblzma-sys/src/manual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub const LZMA_PB_DEFAULT: u32 = 2;

pub const LZMA_BACKWARD_SIZE_MIN: lzma_vli = 4;
pub const LZMA_BACKWARD_SIZE_MAX: lzma_vli = 1 << 34;
pub const LZMA_STREAM_HEADER_SIZE: u32 = 12;

pub const LZMA_VLI_MAX: lzma_vli = u64::MAX / 2;
pub const LZMA_VLI_UNKNOWN: lzma_vli = u64::MAX;
Expand All @@ -99,6 +100,7 @@ pub struct lzma_allocator {
pub opaque: *mut c_void,
}

pub enum lzma_index {}
pub enum lzma_internal {}

#[repr(C)]
Expand Down Expand Up @@ -344,6 +346,17 @@ extern "C" {
b: *const lzma_stream_flags,
) -> lzma_ret;

pub fn lzma_index_buffer_decode(
i: *mut *mut lzma_index,
memlimit: *mut u64,
allocator: *const lzma_allocator,
input: *const u8,
in_pos: *mut size_t,
in_size: size_t,
) -> lzma_ret;
pub fn lzma_index_uncompressed_size(i: *const lzma_index) -> lzma_vli;
pub fn lzma_index_end(i: *mut lzma_index, allocator: *const lzma_allocator);

pub fn lzma_version_number() -> u32;
pub fn lzma_version_string() -> *const c_char;

Expand Down
203 changes: 203 additions & 0 deletions patch.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
diff --git a/benches/backend_comparison.rs b/benches/backend_comparison.rs
index bb9c6be..41d9750 100644
--- a/benches/backend_comparison.rs
+++ b/benches/backend_comparison.rs
@@ -16,21 +16,22 @@ compile_error!("backend_comparison bench requires `xz`, `xz-sys`, or `liblzma-sy
#[cfg(feature = "liblzma-sys")]
use liblzma_sys::{
lzma_crc32, lzma_crc64, lzma_easy_buffer_encode, lzma_stream_buffer_bound,
- lzma_stream_buffer_decode, LZMA_CHECK_CRC64,
+ lzma_stream_buffer_decode, LZMA_CHECK_CRC64, LZMA_OK,
};
#[cfg(feature = "xz")]
-use xz::check::{crc32_fast::lzma_crc32, crc64_fast::lzma_crc64};
-#[cfg(feature = "xz")]
-use xz::common::{
- easy_buffer_encoder::lzma_easy_buffer_encode, stream_buffer_decoder::lzma_stream_buffer_decode,
- stream_buffer_encoder::lzma_stream_buffer_bound,
+use xz::{
+ check::{crc32_fast::lzma_crc32, crc64_fast::lzma_crc64},
+ common::{
+ easy_buffer_encoder::lzma_easy_buffer_encode,
+ stream_buffer_decoder::lzma_stream_buffer_decode,
+ stream_buffer_encoder::lzma_stream_buffer_bound,
+ },
+ types::{LZMA_CHECK_CRC64, LZMA_OK},
};
-#[cfg(feature = "xz")]
-use xz::types::LZMA_CHECK_CRC64;
#[cfg(feature = "xz-sys")]
use xz_sys::{
lzma_crc32, lzma_crc64, lzma_easy_buffer_encode, lzma_stream_buffer_bound,
- lzma_stream_buffer_decode, LZMA_CHECK_CRC64,
+ lzma_stream_buffer_decode, LZMA_CHECK_CRC64, LZMA_OK,
};

#[cfg(feature = "xz")]
@@ -56,7 +57,7 @@ unsafe fn backend_encode(input: &[u8]) -> Vec<u8> {
let bound = lzma_stream_buffer_bound(input.len());
let mut out = vec![0u8; bound];
let mut out_pos: usize = 0;
- lzma_easy_buffer_encode(
+ let ret = lzma_easy_buffer_encode(
6,
LZMA_CHECK_CRC64,
ptr::null(),
@@ -66,6 +67,7 @@ unsafe fn backend_encode(input: &[u8]) -> Vec<u8> {
&mut out_pos,
out.len(),
);
+ assert_eq!(ret, LZMA_OK, "{BACKEND_NAME} encode failed with {ret}");
out.truncate(out_pos);
out
}
@@ -75,7 +77,7 @@ unsafe fn backend_decode(compressed: &[u8], out_size: usize) -> Vec<u8> {
let mut memlimit = u64::MAX;
let mut in_pos = 0usize;
let mut out_pos = 0usize;
- lzma_stream_buffer_decode(
+ let ret = lzma_stream_buffer_decode(
&mut memlimit,
0,
ptr::null(),
@@ -86,6 +88,17 @@ unsafe fn backend_decode(compressed: &[u8], out_size: usize) -> Vec<u8> {
&mut out_pos,
out.len(),
);
+ assert_eq!(ret, LZMA_OK, "{BACKEND_NAME} decode failed with {ret}");
+ assert_eq!(
+ in_pos,
+ compressed.len(),
+ "{BACKEND_NAME} decode left trailing input: consumed {in_pos} of {} bytes",
+ compressed.len()
+ );
+ assert_eq!(
+ out_pos, out_size,
+ "{BACKEND_NAME} decode produced {out_pos} bytes, expected {out_size}"
+ );
out.truncate(out_pos);
out
}
diff --git a/perf-probe/src/main.rs b/perf-probe/src/main.rs
index 37cd579..3a56de6 100644
--- a/perf-probe/src/main.rs
+++ b/perf-probe/src/main.rs
@@ -225,7 +225,7 @@ fn usage() -> String {
let mut message = String::new();
message.push_str("Usage:\n");
message.push_str(
- " cargo run -p perf-probe --release --no-default-features --features <liblzma-sys|xz-sys> -- \\\n",
+ " cargo run -p perf-probe --release --no-default-features --features <xz|xz-sys|liblzma-sys> -- \\\n",
);
message.push_str(" --workload <encode|decode|size|crc32|crc64> [options]\n\n");
message.push_str("Options:\n");
@@ -527,6 +527,16 @@ unsafe fn backend_decode(compressed: &[u8], out_size: usize) -> Vec<u8> {
)
};
assert_eq!(ret, LZMA_OK, "{BACKEND_NAME} decode failed with {ret}");
+ assert_eq!(
+ in_pos,
+ compressed.len(),
+ "{BACKEND_NAME} decode left trailing input: consumed {in_pos} of {} bytes",
+ compressed.len()
+ );
+ assert_eq!(
+ out_pos, out_size,
+ "{BACKEND_NAME} decode produced {out_pos} bytes, expected {out_size}"
+ );
out.truncate(out_pos);
out
}
diff --git a/scripts/compare_api_workloads.sh b/scripts/compare_api_workloads.sh
index 014f70c..15f0b9a 100755
--- a/scripts/compare_api_workloads.sh
+++ b/scripts/compare_api_workloads.sh
@@ -50,7 +50,7 @@ esac
RUST_BIN="$RUST_TARGET/release/examples/$EXAMPLE_NAME"
C_BIN="$C_TARGET/release/examples/$EXAMPLE_NAME"

-env CARGO_TARGET_DIR="$RUST_TARGET" cargo build --example "$EXAMPLE_NAME" --release >/dev/null
+env CARGO_TARGET_DIR="$RUST_TARGET" cargo build --example "$EXAMPLE_NAME" --release --no-default-features --features xz >/dev/null
env LZMA_API_STATIC=1 CARGO_TARGET_DIR="$C_TARGET" cargo build --example "$EXAMPLE_NAME" --release --no-default-features --features liblzma-sys >/dev/null

hyperfine \
diff --git a/scripts/compare_backends.sh b/scripts/compare_backends.sh
index fb5628a..f16fb02 100755
--- a/scripts/compare_backends.sh
+++ b/scripts/compare_backends.sh
@@ -70,7 +70,7 @@ SYSTEST_RUST_CMD="env CARGO_TARGET_DIR=$SYSTEST_RUST_TARGET cargo test -p systes
SYSTEST_C_CMD="env LZMA_API_STATIC=1 CARGO_TARGET_DIR=$SYSTEST_C_TARGET cargo test -p systest --release --no-default-features --features liblzma-sys -- --test-threads=1"

echo "prebuilding root test binaries..."
-env CARGO_TARGET_DIR="$ROOT_RUST_TARGET" cargo test --release --no-run >/dev/null
+env CARGO_TARGET_DIR="$ROOT_RUST_TARGET" cargo test -p liblzma --release --no-default-features --features xz --no-run >/dev/null
env LZMA_API_STATIC=1 CARGO_TARGET_DIR="$ROOT_C_TARGET" cargo test --release --no-default-features --features liblzma-sys --no-run >/dev/null

hyperfine \
diff --git a/scripts/profile_backend.sh b/scripts/profile_backend.sh
index ee74f22..5bcab7e 100755
--- a/scripts/profile_backend.sh
+++ b/scripts/profile_backend.sh
@@ -3,11 +3,10 @@ set -euo pipefail

if [[ $# -lt 2 ]]; then
cat <<'EOF' >&2
-Usage: scripts/profile_backend.sh <c|liblzma-sys|xz|rust|xz-sys|both> <encode|decode|size|crc32|crc64> [backend_probe args...]
+Usage: scripts/profile_backend.sh <c|liblzma-sys|xz|rust|xz-sys> <encode|decode|size|crc32|crc64> [backend_probe args...]

Examples:
scripts/profile_backend.sh xz decode --size 1048576 --iters 500 --warmup 50
- scripts/profile_backend.sh both encode --input-kind random --size 8388608
scripts/profile_backend.sh xz size --input-kind random --size 1048576 --iters 800 --warmup 80

Environment:
@@ -40,10 +39,6 @@ case "$BACKEND" in
TARGET_DIR="target/profile-bench-xz-sys"
BACKEND_ENV=()
;;
- both)
- echo "profile_backend.sh profiles one backend at a time; use xz, xz-sys, or liblzma-sys" >&2
- exit 2
- ;;
*)
echo "unknown backend: $BACKEND" >&2
exit 2
diff --git a/xz/src/common/common.rs b/xz/src/common/common.rs
index ca6108f..b37486d 100644
--- a/xz/src/common/common.rs
+++ b/xz/src/common/common.rs
@@ -120,6 +120,12 @@ pub unsafe fn lzma_bufcpy(
out_pos: *mut size_t,
out_size: size_t,
) -> size_t {
+ if *in_pos > in_size || *out_pos > out_size {
+ return 0;
+ }
+ if (in_0.is_null() && *in_pos != in_size) || (out.is_null() && *out_pos != out_size) {
+ return 0;
+ }
debug_assert!(!in_0.is_null() || *in_pos == in_size);
debug_assert!(!out.is_null() || *out_pos == out_size);
debug_assert!(*in_pos <= in_size);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Runtime guards make subsequent debug_assert!s dead code.

The new early returns cover the exact same conditions as the debug_assert! on lines 179–181 that immediately follow. Those asserts can no longer fire in either debug or release. Either drop the redundant debug_asserts, or keep only the asserts and drop the new guards if silent fallthrough is not desired (the current change effectively converts a debug-time panic into a silent no-op in debug builds).

♻️ Proposed cleanup
     if *in_pos > in_size || *out_pos > out_size {
         return 0;
     }
     if (in_0.is_null() && *in_pos != in_size) || (out.is_null() && *out_pos != out_size) {
         return 0;
     }
-    debug_assert!(!in_0.is_null() || *in_pos == in_size);
-    debug_assert!(!out.is_null() || *out_pos == out_size);
-    debug_assert!(*in_pos <= in_size);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
+ if *in_pos > in_size || *out_pos > out_size {
+ return 0;
+ }
+ if (in_0.is_null() && *in_pos != in_size) || (out.is_null() && *out_pos != out_size) {
+ return 0;
+ }
debug_assert!(!in_0.is_null() || *in_pos == in_size);
debug_assert!(!out.is_null() || *out_pos == out_size);
debug_assert!(*in_pos <= in_size);
if *in_pos > in_size || *out_pos > out_size {
return 0;
}
if (in_0.is_null() && *in_pos != in_size) || (out.is_null() && *out_pos != out_size) {
return 0;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@patch.diff` around lines 173 - 181, The added runtime guards (checking
*in_pos, *out_pos vs in_size/out_size and null checks for in_0/out) make the
following debug_assert!s (the three debug_assert! lines immediately after)
unreachable; remove the redundancy by either deleting those debug_assert! lines
(debug_assert!(!in_0.is_null() || *in_pos == in_size);
debug_assert!(!out.is_null() || *out_pos == out_size); debug_assert!(*in_pos <=
in_size);) or, if you want a debug-time panic instead of a silent return, remove
the new early-return guards and keep the debug_assert!s; update the block around
the checks of in_pos, out_pos, in_size, out_size, in_0 and out accordingly so
only one style (runtime guard or debug_assert) remains.

diff --git a/xz/src/common/stream_decoder.rs b/xz/src/common/stream_decoder.rs
index 70071fc..791d0c3 100644
--- a/xz/src/common/stream_decoder.rs
+++ b/xz/src/common/stream_decoder.rs
@@ -173,7 +173,7 @@ unsafe extern "C" fn stream_decode(
return LZMA_OK;
}
(*coder).pos = 0;
- let mut footer_flags = MaybeUninit::<lzma_stream_flags>::uninit();
+ let mut footer_flags = MaybeUninit::<lzma_stream_flags>::zeroed();
let ret_3: lzma_ret = lzma_stream_footer_decode(
footer_flags.as_mut_ptr(),
::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8,
@@ -244,6 +244,8 @@ unsafe extern "C" fn stream_decode(
::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8,
);
if ret_ != LZMA_OK {
+ lzma_filters_free(filters_ptr, allocator);
+ (*coder).block_options.filters = core::ptr::null_mut();
return ret_;
}
(*coder).block_options.ignore_check = (*coder).ignore_check as lzma_bool;
Loading
Loading