Skip to content

Commit e9662f6

Browse files
committed
This should fix #7976: False validation error for short unpacked records
1 parent 99779f6 commit e9662f6

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

src/jrd/validation.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,21 +2789,44 @@ Validation::RTN Validation::walk_record(jrd_rel* relation, const rhd* header, US
27892789
if (header->rhd_flags & rhd_incomplete)
27902790
{
27912791
p = fragment->rhdf_data;
2792-
length -= offsetof(rhdf, rhdf_data[0]);
2792+
length -= RHDF_SIZE;
27932793
}
27942794
else if (header->rhd_flags & rhd_long_tranum)
27952795
{
27962796
p = ((rhde*) header)->rhde_data;
2797-
length -= offsetof(rhde, rhde_data[0]);
2797+
length -= RHDE_SIZE;
27982798
}
27992799
else
28002800
{
28012801
p = header->rhd_data;
2802-
length -= offsetof(rhd, rhd_data[0]);
2802+
length -= RHD_SIZE;
28032803
}
28042804

2805-
ULONG record_length = (header->rhd_flags & rhd_not_packed) ?
2806-
length : Compressor::getUnpackedLength(length, p);
2805+
const auto format = MET_format(vdr_tdbb, relation, header->rhd_format);
2806+
auto remainingLength = format->fmt_length;
2807+
2808+
auto calculateLength = [fragment, remainingLength](ULONG length, const UCHAR* data)
2809+
{
2810+
if (fragment->rhdf_flags & rhd_not_packed)
2811+
{
2812+
if (length > remainingLength)
2813+
{
2814+
// Short records may be zero-padded up to the fragmented header size.
2815+
// Find out how many zero bytes present inside the tail and adjust
2816+
// the calculated record length accordingly.
2817+
2818+
auto tail = data + remainingLength;
2819+
for (const auto end = data + length; tail < end && !*tail; tail++)
2820+
length--;
2821+
}
2822+
2823+
return length;
2824+
}
2825+
2826+
return Compressor::getUnpackedLength(length, data);
2827+
};
2828+
2829+
remainingLength -= calculateLength(length, p);
28072830

28082831
// Next, chase down fragments, if any
28092832

@@ -2842,33 +2865,30 @@ Validation::RTN Validation::walk_record(jrd_rel* relation, const rhd* header, US
28422865
if (fragment->rhdf_flags & rhd_incomplete)
28432866
{
28442867
p = fragment->rhdf_data;
2845-
length -= offsetof(rhdf, rhdf_data[0]);
2868+
length -= RHDF_SIZE;
28462869
}
28472870
else if (fragment->rhdf_flags & rhd_long_tranum)
28482871
{
28492872
p = ((rhde*) fragment)->rhde_data;
2850-
length -= offsetof(rhde, rhde_data[0]);
2873+
length -= RHDE_SIZE;
28512874
}
28522875
else
28532876
{
28542877
p = ((rhd*) fragment)->rhd_data;
2855-
length -= offsetof(rhd, rhd_data[0]);
2878+
length -= RHD_SIZE;
28562879
}
28572880

2858-
record_length += (fragment->rhdf_flags & rhd_not_packed) ?
2859-
length : Compressor::getUnpackedLength(length, p);
2881+
remainingLength -= calculateLength(length, p);
28602882

28612883
page_number = fragment->rhdf_f_page;
28622884
line_number = fragment->rhdf_f_line;
28632885
flags = fragment->rhdf_flags;
28642886
release_page(&window);
28652887
}
28662888

2867-
// Check out record length and format
2868-
2869-
const Format* format = MET_format(vdr_tdbb, relation, header->rhd_format);
2889+
// Validate unpacked record length
28702890

2871-
if (!delta_flag && record_length != format->fmt_length)
2891+
if (!delta_flag && remainingLength != 0)
28722892
return corrupt(VAL_REC_WRONG_LENGTH, relation, number.getValue());
28732893

28742894
return rtn_ok;

0 commit comments

Comments
 (0)