Don't strip trailing null byte from binary records in Altium parser
ReadProperties() unconditionally stripped a trailing 0x00 byte from all records. This is correct for text records where 0x00 is a string terminator, but binary records contain raw compressed data where 0x00 is valid payload. When a zlib stream happened to end with 0x00, stripping it caused ReadFullPascalString() to throw out_of_range, crashing Altium .SchLib imports. Only strip the null byte for non-binary records. Fixes https://gitlab.com/kicad/code/kicad/-/issues/23013
This commit is contained in:
@@ -382,7 +382,7 @@ std::map<wxString, wxString> ALTIUM_BINARY_PARSER::ReadProperties(
|
||||
|
||||
// we use std::string because std::string can handle NULL-bytes
|
||||
// wxString would end the string at the first NULL-byte
|
||||
std::string str = std::string( m_pos, length - ( hasNullByte ? 1 : 0 ) );
|
||||
std::string str = std::string( m_pos, length - ( ( hasNullByte && !isBinary ) ? 1 : 0 ) );
|
||||
m_pos += length;
|
||||
|
||||
if( isBinary )
|
||||
|
||||
@@ -286,4 +286,40 @@ BOOST_DATA_TEST_CASE( ReadProperties,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verify that binary records ending with 0x00 are not truncated.
|
||||
* Regression test for https://gitlab.com/kicad/code/kicad/-/issues/23013
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( ReadPropertiesBinaryNullBytePreserved )
|
||||
{
|
||||
// Simulate a binary record whose payload ends with 0x00.
|
||||
// The MSB of the 4-byte length field flags the record as binary.
|
||||
const char binaryPayload[] = { 0x01, 0x02, 0x03, 0x00 };
|
||||
const uint32_t payloadLen = sizeof( binaryPayload );
|
||||
const uint32_t lengthField = payloadLen | 0x01000000;
|
||||
|
||||
size_t totalSize = 4 + payloadLen;
|
||||
std::unique_ptr<char[]> content = std::make_unique<char[]>( totalSize );
|
||||
|
||||
std::memcpy( content.get(), &lengthField, 4 );
|
||||
std::memcpy( content.get() + 4, binaryPayload, payloadLen );
|
||||
|
||||
ALTIUM_BINARY_PARSER parser( content, totalSize );
|
||||
|
||||
std::string receivedData;
|
||||
auto binaryHandler = [&]( const std::string& aData ) -> std::map<wxString, wxString>
|
||||
{
|
||||
receivedData = aData;
|
||||
return {};
|
||||
};
|
||||
|
||||
parser.ReadProperties( binaryHandler );
|
||||
|
||||
BOOST_CHECK_EQUAL( parser.HasParsingError(), false );
|
||||
BOOST_CHECK_EQUAL( parser.GetRemainingBytes(), 0 );
|
||||
BOOST_CHECK_EQUAL( receivedData.size(), payloadLen );
|
||||
BOOST_CHECK_EQUAL( receivedData.back(), '\0' );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Reference in New Issue
Block a user