diff --git a/common/io/altium/altium_binary_parser.cpp b/common/io/altium/altium_binary_parser.cpp index 131e09a391..c1a0ad293d 100644 --- a/common/io/altium/altium_binary_parser.cpp +++ b/common/io/altium/altium_binary_parser.cpp @@ -382,7 +382,7 @@ std::map 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 ) diff --git a/qa/tests/common/io/altium/test_altium_parser.cpp b/qa/tests/common/io/altium/test_altium_parser.cpp index a9e6635cb6..8e6be4e7bd 100644 --- a/qa/tests/common/io/altium/test_altium_parser.cpp +++ b/qa/tests/common/io/altium/test_altium_parser.cpp @@ -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 content = std::make_unique( 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 + { + 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()