diff --git a/include/SZ3/predictor/ComposedPredictor.hpp b/include/SZ3/predictor/ComposedPredictor.hpp index 4e4b2b16..46281ac9 100644 --- a/include/SZ3/predictor/ComposedPredictor.hpp +++ b/include/SZ3/predictor/ComposedPredictor.hpp @@ -72,8 +72,12 @@ class ComposedPredictor : public concepts::PredictorInterface { if (selection_size > 0) { HuffmanEncoder selection_encoder; selection_encoder.load(c, remaining_length); + /// decode() advances `c` past the encoded stream but does not update `remaining_length`; + /// account for exactly the bytes it consumed so the bound stays tight for later reads. + const uchar *decode_start = c; this->selection = selection_encoder.decode(c, selection_size); selection_encoder.postprocess_decode(); + remaining_length -= static_cast(c - decode_start); } } diff --git a/include/SZ3/predictor/RegressionPredictor.hpp b/include/SZ3/predictor/RegressionPredictor.hpp index 51b3a089..f23b9aa4 100644 --- a/include/SZ3/predictor/RegressionPredictor.hpp +++ b/include/SZ3/predictor/RegressionPredictor.hpp @@ -114,9 +114,14 @@ class RegressionPredictor : public concepts::PredictorInterface { quantizer_liner.load(c, remaining_length); HuffmanEncoder encoder = HuffmanEncoder(); encoder.load(c, remaining_length); + /// decode() advances `c` past the encoded stream but does not update `remaining_length`; + /// account for exactly the bytes it consumed. The previous `coeff_size * sizeof(int)` used the + /// uncompressed index count, which overshoots the (Huffman-compressed) stream and understates + /// remaining_length, making a later encoder.load() bound check spuriously reject valid data. + const uchar *decode_start = c; regression_coeff_quant_inds = encoder.decode(c, coeff_size); encoder.postprocess_decode(); - remaining_length -= coeff_size * sizeof(int); + remaining_length -= static_cast(c - decode_start); std::fill(current_coeffs.begin(), current_coeffs.end(), 0); regression_coeff_index = 0; }