ByteVector: Skip whitespace in fromBase64 (#1484)

ASCII whitespace (space, tab, CR, LF) is skipped before decoding, so
line-wrapped base64, such as a METADATA_BLOCK_PICTURE wrapped every 76
characters, decodes instead of returning an empty vector. Other
invalid characters still do.
This commit is contained in:
Ryan Francesconi
2026-11-01 06:57:14 +01:00
committed by GitHub
parent 40503ebd07
commit 629b707fc5
4 changed files with 66 additions and 1 deletions
+12
View File
@@ -628,6 +628,18 @@ public:
CPPUNIT_ASSERT_EQUAL(sempty,ByteVector::fromBase64(invalid));
}
// Skip whitespace, as in line wrapped input
{
CPPUNIT_ASSERT_EQUAL(s1,ByteVector::fromBase64("YW55IGNhcm5h\nbCBwbGVhc3VyZS4="));
CPPUNIT_ASSERT_EQUAL(s1,ByteVector::fromBase64("YW55IGNhcm5hbCBw\r\nbGVhc3VyZS4=\r\n"));
CPPUNIT_ASSERT_EQUAL(s3,ByteVector::fromBase64(" YW55 IGNh\tcm5hbCBwbGVhc3Vy\n"));
CPPUNIT_ASSERT_EQUAL(sempty,ByteVector::fromBase64(" \r\n\t"));
// Whitespace does not make otherwise invalid input valid
CPPUNIT_ASSERT_EQUAL(sempty,ByteVector::fromBase64("YW55\nIGNh-cm5hbCBwbGVhc3VyZS4="));
CPPUNIT_ASSERT_EQUAL(sempty,ByteVector::fromBase64("YW55IGNhcm5hbCBwbGVhc3VyZQ=\n"));
}
}
void testEmpty()
+38
View File
@@ -47,6 +47,7 @@ class TestXiphComment : public CppUnit::TestFixture
CPPUNIT_TEST(testClearComment);
CPPUNIT_TEST(testRemoveFields);
CPPUNIT_TEST(testPicture);
CPPUNIT_TEST(testWrappedPicture);
CPPUNIT_TEST(testLowercaseFields);
CPPUNIT_TEST_SUITE_END();
@@ -193,6 +194,43 @@ public:
}
}
void testWrappedPicture()
{
ScopedFileCopy copy("empty", ".ogg");
string newname = copy.fileName();
FLAC::Picture picture;
picture.setType(FLAC::Picture::FrontCover);
picture.setMimeType("image/jpeg");
picture.setData(ByteVector(200, 'x'));
// Base64 with a line break every 76 characters, as MIME style encoders write it.
const ByteVector base64 = picture.render().toBase64();
ByteVector wrapped;
for(unsigned int i = 0; i < base64.size(); i += 76) {
wrapped.append(base64.mid(i, 76));
wrapped.append('\n');
}
{
Vorbis::File f(newname.c_str());
f.tag()->addField("METADATA_BLOCK_PICTURE", String(wrapped, String::Latin1));
f.save();
}
{
Vorbis::File f(newname.c_str());
CPPUNIT_ASSERT_EQUAL(1U, f.tag()->pictureList().size());
CPPUNIT_ASSERT_EQUAL(ByteVector(200, 'x'), f.tag()->pictureList().front()->data());
f.tag()->setTitle("Title");
f.save();
}
{
Vorbis::File f(newname.c_str());
CPPUNIT_ASSERT_EQUAL(String("Title"), f.tag()->title());
CPPUNIT_ASSERT_EQUAL(1U, f.tag()->pictureList().size());
}
}
void testLowercaseFields()
{
const ScopedFileCopy copy("lowercase-fields", ".ogg");