Skip to content

Fix Config::load reading one byte past the end of the config - #131

Open
alexey-milovidov wants to merge 1 commit into
szcompressor:masterfrom
ClickHouse:ch-fix-config-load-end-pointer
Open

Fix Config::load reading one byte past the end of the config#131
alexey-milovidov wants to merge 1 commit into
szcompressor:masterfrom
ClickHouse:ch-fix-config-load-end-pointer

Conversation

@alexey-milovidov

@alexey-milovidov alexey-milovidov commented Jun 29, 2026

Copy link
Copy Markdown

Problem

Config::save writes the config size as confSize = c - c0, i.e. the total size of the serialized config including the one-byte length prefix it reserves at the start.

In Config::load, the end pointer is computed as c + confSize after the prefix byte has already been read, so it ends up one byte past the real end of the config blob:

read(confSize, c);        // c now points just after the 1-byte prefix
auto c1 = c + confSize;   // == c0 + 1 + confSize  -> one byte too far

The if (c < c1) guards that read the optional trailing fields then use a boundary that is one byte too far. For a config that does not contain all of the trailing fields, this makes load read one field past the end of the config.

Fix

Compute the end of the config relative to its start:

const unsigned char* c0 = c;
read(confSize, c);
auto c1 = c0 + confSize;

No format change; this only corrects the in-memory end pointer used by load.

Context

Found while integrating SZ3 as an experimental compression codec in ClickHouse: ClickHouse/ClickHouse#108788

`Config::save` writes `confSize = c - c0`, i.e. the total size of the
serialized config including the one-byte length prefix. In `Config::load`
the end pointer was computed as `c + confSize` after the prefix byte had
already been consumed, so it pointed one byte past the real end of the
config blob.

The `if (c < c1)` guards that read the optional trailing fields then use a
boundary that is one byte too far. For a config that does not contain all
of the trailing fields (e.g. data produced by a build with fewer fields)
this makes `load` read one field past the end of the config.

Compute the end as `c0 + confSize` instead.
ayzk added a commit that referenced this pull request Sep 1, 2026
Bug fixes only: no compressed-format change and no interface signature change.

Covers the reviewed content of #131, #133, #134, #135, #137, #138 and #139, plus the
findings ported from the fz branch. #132 is only partly covered -- see the PR body for
the four exclusions and the measurement behind each.

31 dataset x algorithm x error-bound combinations are byte-identical to master, and every
master-produced file still decompresses to the same bytes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant