diff --git a/abstracttrack.cpp b/abstracttrack.cpp index b48f658..b3c4dff 100644 --- a/abstracttrack.cpp +++ b/abstracttrack.cpp @@ -211,7 +211,7 @@ string AbstractTrack::description() const void AbstractTrack::parseHeader(Diagnostics &diag) { m_headerValid = false; - m_istream->seekg(m_startOffset, ios_base::beg); + m_istream->seekg(static_cast(m_startOffset), ios_base::beg); try { internalParseHeader(diag); m_headerValid = true; diff --git a/adts/adtsstream.cpp b/adts/adtsstream.cpp index e49a196..ccf2fda 100644 --- a/adts/adtsstream.cpp +++ b/adts/adtsstream.cpp @@ -17,6 +17,8 @@ namespace TagParser { void AdtsStream::internalParseHeader(Diagnostics &diag) { + VAR_UNUSED(diag) + //static const string context("parsing ADTS frame header"); if (!m_istream) { throw NoDataFoundException(); @@ -28,7 +30,7 @@ void AdtsStream::internalParseHeader(Diagnostics &diag) } else { m_size = static_cast(m_istream->tellg()) + 125u - m_startOffset; } - m_istream->seekg(m_startOffset, ios_base::beg); + m_istream->seekg(static_cast(m_startOffset), ios_base::beg); // parse frame header m_firstFrame.parseHeader(m_reader); m_format = Mpeg4AudioObjectIds::idToMediaFormat(m_firstFrame.mpeg4AudioObjectId()); diff --git a/avc/avcconfiguration.cpp b/avc/avcconfiguration.cpp index f9da90c..90722a3 100644 --- a/avc/avcconfiguration.cpp +++ b/avc/avcconfiguration.cpp @@ -5,6 +5,8 @@ #include +#include + using namespace std; using namespace IoUtilities; @@ -42,7 +44,7 @@ void AvcConfiguration::parse(BinaryReader &reader, uint64 maxSize) } spsInfos.emplace_back(); try { - spsInfos.back().parse(reader, maxSize); + spsInfos.back().parse(reader, maxSize > numeric_limits::max() ? numeric_limits::max() : static_cast(maxSize)); } catch (const TruncatedDataException &) { // TODO: log parsing error if (spsInfos.back().size > maxSize - 2) { @@ -65,7 +67,7 @@ void AvcConfiguration::parse(BinaryReader &reader, uint64 maxSize) } ppsInfos.emplace_back(); try { - ppsInfos.back().parse(reader, maxSize); + ppsInfos.back().parse(reader, maxSize > numeric_limits::max() ? numeric_limits::max() : static_cast(maxSize)); } catch (const TruncatedDataException &) { // TODO: log parsing error if (ppsInfos.back().size > maxSize - 2) { diff --git a/flac/flacmetadata.cpp b/flac/flacmetadata.cpp index 672ba71..5661600 100644 --- a/flac/flacmetadata.cpp +++ b/flac/flacmetadata.cpp @@ -108,29 +108,39 @@ void FlacMetaDataBlockPicture::parse(istream &inputStream, uint32 maxSize) /*! * \brief Returns the number of bytes make() will write. * \remarks Any changes to the object will invalidate this value. + * \throws Throws an InvalidDataException() if the assigned data is too big. */ uint32 FlacMetaDataBlockPicture::requiredSize() const { - return 32 + m_value.mimeType().size() + m_value.description().size() + m_value.dataSize(); + const auto requiredSize(32 + m_value.mimeType().size() + m_value.description().size() + m_value.dataSize()); + if (requiredSize > numeric_limits::max()) { + throw InvalidDataException(); + } + return static_cast(requiredSize); } /*! * \brief Makes the FLAC "METADATA_BLOCK_PICTURE". + * \throws Throws an InvalidDataException() if the assigned data can not be serialized into a "METADATA_BLOCK_PICTURE" structure. */ void FlacMetaDataBlockPicture::make(ostream &outputStream) { + if (m_value.mimeType().size() > numeric_limits::max() || m_value.description().size() > numeric_limits::max() + || m_value.dataSize() > numeric_limits::max()) { + throw InvalidDataException(); + } BinaryWriter writer(&outputStream); writer.writeUInt32BE(pictureType()); - writer.writeUInt32BE(m_value.mimeType().size()); + writer.writeUInt32BE(static_cast(m_value.mimeType().size())); writer.writeString(m_value.mimeType()); - writer.writeUInt32BE(m_value.description().size()); + writer.writeUInt32BE(static_cast(m_value.description().size())); writer.writeString(m_value.description()); writer.writeUInt32BE(0); // skip width writer.writeUInt32BE(0); // skip height writer.writeUInt32BE(0); // skip color depth writer.writeUInt32BE(0); // skip number of colors used - writer.writeUInt32BE(m_value.dataSize()); - writer.write(value().dataPointer(), m_value.dataSize()); + writer.writeUInt32BE(static_cast(m_value.dataSize())); + writer.write(value().dataPointer(), static_cast(m_value.dataSize())); } } // namespace TagParser diff --git a/flac/flacstream.cpp b/flac/flacstream.cpp index 8f23d0b..0efd098 100644 --- a/flac/flacstream.cpp +++ b/flac/flacstream.cpp @@ -71,7 +71,7 @@ void FlacStream::internalParseHeader(Diagnostics &diag) throw NoDataFoundException(); } - m_istream->seekg(m_startOffset, ios_base::beg); + m_istream->seekg(static_cast(m_startOffset), ios_base::beg); char buffer[0x22]; // check signature @@ -159,7 +159,7 @@ void FlacStream::internalParseHeader(Diagnostics &diag) // TODO: check first FLAC frame } - m_streamOffset = m_istream->tellg(); + m_streamOffset = static_cast(m_istream->tellg()); } /*! @@ -177,7 +177,7 @@ void FlacStream::internalParseHeader(Diagnostics &diag) uint32 FlacStream::makeHeader(ostream &outputStream, Diagnostics &diag) { istream &originalStream = m_mediaFileInfo.stream(); - originalStream.seekg(m_startOffset + 4); + originalStream.seekg(static_cast(m_startOffset + 4)); CopyHelper<512> copy; // write signature @@ -247,6 +247,7 @@ uint32 FlacStream::makeHeader(ostream &outputStream, Diagnostics &diag) outputStream.seekp(lastStartOffset); header.makeHeader(outputStream); outputStream.seekp(static_cast(dataSize), ios_base::cur); + lastActuallyWrittenHeader = header; // write cover fields separately as "METADATA_BLOCK_PICTURE" if (header.isLast()) { @@ -255,13 +256,37 @@ uint32 FlacStream::makeHeader(ostream &outputStream, Diagnostics &diag) header.setType(FlacMetaDataBlockType::Picture); const auto coverFields = m_vorbisComment->fields().equal_range(coverId); for (auto i = coverFields.first; i != coverFields.second;) { - lastStartOffset = outputStream.tellp(); - FlacMetaDataBlockPicture pictureBlock(i->second.value()); - pictureBlock.setPictureType(i->second.typeInfo()); - header.setDataSize(pictureBlock.requiredSize()); - header.setLast(++i == coverFields.second); - header.makeHeader(outputStream); - pictureBlock.make(outputStream); + const auto lastCoverStartOffset = outputStream.tellp(); + + try { + // write the structure + FlacMetaDataBlockPicture pictureBlock(i->second.value()); + pictureBlock.setPictureType(i->second.typeInfo()); + header.setDataSize(pictureBlock.requiredSize()); + header.setLast(++i == coverFields.second); + header.makeHeader(outputStream); + pictureBlock.make(outputStream); + + // update variables to handle the "isLast" flag + lastStartOffset = lastCoverStartOffset; + lastActuallyWrittenHeader = header; + + } catch (const Failure &) { + // we can expect nothing is written in the error case except the FLAC header, so + // -> just add an error message + diag.emplace_back(DiagLevel::Critical, "Unable to serialize \"METADATA_BLOCK_PICTURE\" from assigned value.", + "write \"METADATA_BLOCK_PICTURE\" to FLAC stream"); + // -> and to recover, go back to where we were before + outputStream.seekp(lastCoverStartOffset); + } + } + + // adjust "isLast" flag if neccassary + if (!lastActuallyWrittenHeader.isLast()) { + outputStream.seekp(lastStartOffset); + lastActuallyWrittenHeader.setLast(true); + lastActuallyWrittenHeader.makeHeader(outputStream); + outputStream.seekp(lastActuallyWrittenHeader.dataSize()); } return static_cast(lastStartOffset); diff --git a/id3/id3genres.cpp b/id3/id3genres.cpp index 59b7ec8..52e25fe 100644 --- a/id3/id3genres.cpp +++ b/id3/id3genres.cpp @@ -40,7 +40,7 @@ const char **Id3Genres::genreNames() */ int Id3Genres::indexFromString(const string &genre) { - const char **ptr = genreNames(); + const char *const *ptr = genreNames(); for (int index = 0; index < genreCount(); ++ptr, ++index) { if (genre == *ptr) { return index; diff --git a/id3/id3v2frame.cpp b/id3/id3v2frame.cpp index 241e2e6..8208539 100644 --- a/id3/id3v2frame.cpp +++ b/id3/id3v2frame.cpp @@ -25,6 +25,9 @@ namespace Id3v2TextEncodingBytes { enum Id3v2TextEncodingByte : byte { Ascii, Utf16WithBom, Utf16BigEndianWithoutBom, Utf8 }; } +/// \brief The maximum (supported) size of an ID3v2Frame. +constexpr auto maxId3v2FrameDataSize(numeric_limits::max() - 15); + /*! * \class Media::Id3v2Frame * \brief The Id3v2Frame class is used by Id3v2Tag to store the fields. @@ -213,7 +216,11 @@ void Id3v2Frame::parse(BinaryReader &reader, uint32 version, uint32 maximalSize, diag.emplace_back(DiagLevel::Critical, "Decompressing failed (unknown reason).", context); throw InvalidDataException(); } - m_dataSize = decompressedSize; + if (decompressedSize > maxId3v2FrameDataSize) { + diag.emplace_back(DiagLevel::Critical, "The decompressed data exceeds the maximum supported frame size.", context); + throw InvalidDataException(); + } + m_dataSize = static_cast(decompressedSize); } else { buffer = make_unique(m_dataSize); reader.read(buffer.get(), m_dataSize); @@ -222,7 +229,7 @@ void Id3v2Frame::parse(BinaryReader &reader, uint32 version, uint32 maximalSize, // -> get tag value depending of field type if (Id3v2FrameIds::isTextFrame(id())) { // frame contains text - TagTextEncoding dataEncoding = parseTextEncodingByte(*buffer.get(), diag); // the first byte stores the encoding + TagTextEncoding dataEncoding = parseTextEncodingByte(static_cast(*buffer.get()), diag); // the first byte stores the encoding if ((version >= 3 && (id() == Id3v2FrameIds::lTrackPosition || id() == Id3v2FrameIds::lDiskPosition)) || (version < 3 && id() == Id3v2FrameIds::sTrackPosition)) { // the track number or the disk number frame @@ -464,7 +471,11 @@ Id3v2FrameMaker::Id3v2FrameMaker(Id3v2Frame &frame, byte version, Diagnostics &d } else { // make unknown frame - m_data = make_unique(m_decompressedSize = value.dataSize()); + if (value.dataSize() > maxId3v2FrameDataSize) { + diag.emplace_back(DiagLevel::Critical, "Assigned value exceeds maximum size.", context); + throw InvalidDataException(); + } + m_data = make_unique(m_decompressedSize = static_cast(value.dataSize())); copy(value.dataPointer(), value.dataPointer() + m_decompressedSize, m_data.get()); } } catch (const ConversionException &) { @@ -479,9 +490,9 @@ Id3v2FrameMaker::Id3v2FrameMaker(Id3v2Frame &frame, byte version, Diagnostics &d // apply compression if frame should be compressed if (version >= 3 && m_frame.isCompressed()) { - m_dataSize = compressBound(m_decompressedSize); - auto compressedData = make_unique(m_decompressedSize); - switch (compress(reinterpret_cast(compressedData.get()), reinterpret_cast(&m_dataSize), + auto compressedSize = compressBound(m_decompressedSize); + auto compressedData = make_unique(compressedSize); + switch (compress(reinterpret_cast(compressedData.get()), reinterpret_cast(&compressedSize), reinterpret_cast(m_data.get()), m_decompressedSize)) { case Z_MEM_ERROR: diag.emplace_back(DiagLevel::Critical, "Decompressing failed. The source buffer was too small.", context); @@ -491,7 +502,12 @@ Id3v2FrameMaker::Id3v2FrameMaker(Id3v2Frame &frame, byte version, Diagnostics &d throw InvalidDataException(); case Z_OK:; } + if (compressedSize > maxId3v2FrameDataSize) { + diag.emplace_back(DiagLevel::Critical, "Compressed size exceeds maximum data size.", context); + throw InvalidDataException(); + } m_data.swap(compressedData); + m_dataSize = static_cast(compressedSize); } else { m_dataSize = m_decompressedSize; } @@ -744,15 +760,15 @@ void Id3v2Frame::parseLegacyPicture(const char *buffer, std::size_t maxSize, Tag throw TruncatedDataException(); } const char *end = buffer + maxSize; - auto dataEncoding = parseTextEncodingByte(*buffer, diag); // the first byte stores the encoding + auto dataEncoding = parseTextEncodingByte(static_cast(*buffer), diag); // the first byte stores the encoding typeInfo = static_cast(*(buffer + 4)); - auto substr = parseSubstring(buffer + 5, end - 5 - buffer, dataEncoding, true, diag); + auto substr = parseSubstring(buffer + 5, static_cast(end - 5 - buffer), dataEncoding, true, diag); tagValue.setDescription(string(get<0>(substr), get<1>(substr)), dataEncoding); if (get<2>(substr) >= end) { diag.emplace_back(DiagLevel::Critical, "Picture frame is incomplete (actual data is missing).", context); throw TruncatedDataException(); } - tagValue.assignData(get<2>(substr), end - get<2>(substr), TagDataType::Picture, dataEncoding); + tagValue.assignData(get<2>(substr), static_cast(end - get<2>(substr)), TagDataType::Picture, dataEncoding); } /*! @@ -766,7 +782,7 @@ void Id3v2Frame::parsePicture(const char *buffer, std::size_t maxSize, TagValue { static const string context("parsing ID3v2.3 picture frame"); const char *end = buffer + maxSize; - auto dataEncoding = parseTextEncodingByte(*buffer, diag); // the first byte stores the encoding + auto dataEncoding = parseTextEncodingByte(static_cast(*buffer), diag); // the first byte stores the encoding auto mimeTypeEncoding = TagTextEncoding::Latin1; auto substr = parseSubstring(buffer + 1, maxSize - 1, mimeTypeEncoding, true, diag); if (get<1>(substr)) { @@ -781,13 +797,13 @@ void Id3v2Frame::parsePicture(const char *buffer, std::size_t maxSize, TagValue diag.emplace_back(DiagLevel::Critical, "Picture frame is incomplete (description and actual data are missing).", context); throw TruncatedDataException(); } - substr = parseSubstring(get<2>(substr), end - get<2>(substr), dataEncoding, true, diag); + substr = parseSubstring(get<2>(substr), static_cast(end - get<2>(substr)), dataEncoding, true, diag); tagValue.setDescription(string(get<0>(substr), get<1>(substr)), dataEncoding); if (get<2>(substr) >= end) { diag.emplace_back(DiagLevel::Critical, "Picture frame is incomplete (actual data is missing).", context); throw TruncatedDataException(); } - tagValue.assignData(get<2>(substr), end - get<2>(substr), TagDataType::Picture, dataEncoding); + tagValue.assignData(get<2>(substr), static_cast(end - get<2>(substr)), TagDataType::Picture, dataEncoding); } /*! @@ -804,7 +820,7 @@ void Id3v2Frame::parseComment(const char *buffer, std::size_t dataSize, TagValue diag.emplace_back(DiagLevel::Critical, "Comment frame is incomplete.", context); throw TruncatedDataException(); } - TagTextEncoding dataEncoding = parseTextEncodingByte(*buffer, diag); + TagTextEncoding dataEncoding = parseTextEncodingByte(static_cast(*buffer), diag); if (*(++buffer)) { tagValue.setLanguage(string(buffer, 3)); } @@ -814,7 +830,7 @@ void Id3v2Frame::parseComment(const char *buffer, std::size_t dataSize, TagValue diag.emplace_back(DiagLevel::Critical, "Comment frame is incomplete (description not terminated?).", context); throw TruncatedDataException(); } - substr = parseSubstring(get<2>(substr), end - get<2>(substr), dataEncoding, false, diag); + substr = parseSubstring(get<2>(substr), static_cast(end - get<2>(substr)), dataEncoding, false, diag); tagValue.assignData(get<0>(substr), get<1>(substr), TagDataType::Text, dataEncoding); } @@ -852,14 +868,14 @@ void Id3v2Frame::makeEncodingAndData( case TagTextEncoding::Unspecified: // assumption // allocate buffer buffer = make_unique(bufferSize = 1 + dataSize + 1); - buffer[0] = makeTextEncodingByte(encoding); // set text encoding byte + buffer[0] = static_cast(makeTextEncodingByte(encoding)); // set text encoding byte bufferDataAddress = buffer.get() + 1; break; case TagTextEncoding::Utf16LittleEndian: case TagTextEncoding::Utf16BigEndian: // allocate buffer buffer = make_unique(bufferSize = 1 + 2 + dataSize + 2); - buffer[0] = makeTextEncodingByte(encoding); // set text encoding byte + buffer[0] = static_cast(makeTextEncodingByte(encoding)); // set text encoding byte ConversionUtilities::LE::getBytes( encoding == TagTextEncoding::Utf16LittleEndian ? static_cast(0xFEFF) : static_cast(0xFFFE), buffer.get() + 1); bufferDataAddress = buffer.get() + 3; @@ -919,7 +935,7 @@ void Id3v2Frame::makeLegacyPicture(unique_ptr &buffer, uint32 &bufferSiz // note: encoding byte + image format + picture type byte + description size + 1 or 2 null bytes (depends on encoding) + data size char *offset = buffer.get(); // write encoding byte - *offset = makeTextEncodingByte(descriptionEncoding); + *offset = static_cast(makeTextEncodingByte(descriptionEncoding)); // write mime type const char *imageFormat; if (picture.mimeType() == "image/jpeg") { @@ -935,7 +951,7 @@ void Id3v2Frame::makeLegacyPicture(unique_ptr &buffer, uint32 &bufferSiz } strncpy(++offset, imageFormat, 3); // write picture type - *(offset += 3) = typeInfo; + *(offset += 3) = static_cast(typeInfo); // write description offset += makeBom(offset + 1, descriptionEncoding); if (convertedDescription.first) { @@ -988,12 +1004,12 @@ void Id3v2Frame::makePicture(std::unique_ptr &buffer, uint32 &bufferSize // note: encoding byte + mime type size + 0 byte + picture type byte + description size + 1 or 4 null bytes (depends on encoding) + data size char *offset = buffer.get(); // write encoding byte - *offset = makeTextEncodingByte(descriptionEncoding); + *offset = static_cast(makeTextEncodingByte(descriptionEncoding)); // write mime type picture.mimeType().copy(++offset, mimeTypeSize); *(offset += mimeTypeSize) = 0x00; // terminate mime type // write picture type - *(++offset) = typeInfo; + *(++offset) = static_cast(typeInfo); // write description offset += makeBom(offset + 1, descriptionEncoding); if (convertedDescription.first) { @@ -1045,7 +1061,7 @@ void Id3v2Frame::makeComment(unique_ptr &buffer, uint32 &bufferSize, con // note: encoding byte + language + description size + actual data size + BOMs and termination char *offset = buffer.get(); // write encoding - *offset = makeTextEncodingByte(encoding); + *offset = static_cast(makeTextEncodingByte(encoding)); // write language for (unsigned int i = 0; i < 3; ++i) { *(++offset) = (lng.length() > i) ? lng[i] : 0x00; diff --git a/id3/id3v2tag.cpp b/id3/id3v2tag.cpp index 8df0bae..e150d17 100644 --- a/id3/id3v2tag.cpp +++ b/id3/id3v2tag.cpp @@ -496,6 +496,8 @@ Id3v2TagMaker::Id3v2TagMaker(Id3v2Tag &tag, Diagnostics &diag) */ void Id3v2TagMaker::make(std::ostream &stream, uint32 padding, Diagnostics &diag) { + VAR_UNUSED(diag) + BinaryWriter writer(&stream); // write header diff --git a/matroska/ebmlelement.cpp b/matroska/ebmlelement.cpp index 614d5d4..5ed712b 100644 --- a/matroska/ebmlelement.cpp +++ b/matroska/ebmlelement.cpp @@ -77,7 +77,7 @@ void EbmlElement::internalParse(Diagnostics &diag) diag.emplace_back(DiagLevel::Critical, argsToString("The EBML element at ", startOffset(), " is truncated or does not exist."), context); throw TruncatedDataException(); } - stream().seekg(startOffset()); + stream().seekg(static_cast(startOffset())); // read ID char buf[maximumIdLengthSupported() > maximumSizeLengthSupported() ? maximumIdLengthSupported() : maximumSizeLengthSupported()] = { 0 }; @@ -144,7 +144,8 @@ void EbmlElement::internalParse(Diagnostics &diag) } // read size - beg = static_cast(stream().peek()), mask = 0x80; + beg = static_cast(stream().peek()); + mask = 0x80; m_sizeLength = 1; if ((m_sizeUnknown = (beg == 0xFF))) { // this indicates that the element size is unknown @@ -225,7 +226,7 @@ void EbmlElement::internalParse(Diagnostics &diag) */ std::string EbmlElement::readString() { - stream().seekg(dataOffset()); + stream().seekg(static_cast(dataOffset())); return reader().readString(dataSize()); } @@ -237,13 +238,11 @@ std::string EbmlElement::readString() */ uint64 EbmlElement::readUInteger() { - char buff[sizeof(uint64)] = { 0 }; - int i = static_cast(sizeof(buff)) - dataSize(); - if (i < 0) { - i = 0; - } - stream().seekg(dataOffset(), ios_base::beg); - stream().read(buff + i, sizeof(buff) - i); + constexpr DataSizeType maxBytesToRead = 8; + char buff[maxBytesToRead] = { 0 }; + const auto bytesToSkip = maxBytesToRead - min(dataSize(), maxBytesToRead); + stream().seekg(static_cast(dataOffset()), ios_base::beg); + stream().read(buff + bytesToSkip, static_cast(sizeof(buff) - bytesToSkip)); return BE::toUInt64(buff); } @@ -253,10 +252,10 @@ uint64 EbmlElement::readUInteger() */ float64 EbmlElement::readFloat() { - stream().seekg(dataOffset()); + stream().seekg(static_cast(dataOffset())); switch (dataSize()) { case sizeof(float32): - return reader().readFloat32BE(); + return static_cast(reader().readFloat32BE()); case sizeof(float64): return reader().readFloat64BE(); default: @@ -319,7 +318,7 @@ byte EbmlElement::calculateSizeDenotationLength(uint64 size) byte EbmlElement::makeId(GenericFileElement::IdentifierType id, char *buff) { if (id <= 0xFF) { - *buff = static_cast(id); + *buff = static_cast(id); return 1; } else if (id <= 0x7FFF) { BE::getBytes(static_cast(id), buff); @@ -345,7 +344,7 @@ byte EbmlElement::makeId(GenericFileElement::IdentifierType id, char *buff) byte EbmlElement::makeSizeDenotation(uint64 size, char *buff) { if (size < 126) { - *buff = static_cast(size | 0x80); + *buff = static_cast(size | 0x80); return 1; } else if (size <= 16382ul) { BE::getBytes(static_cast(size | 0x4000), buff); @@ -383,7 +382,7 @@ byte EbmlElement::makeSizeDenotation(uint64 size, char *buff) byte EbmlElement::makeSizeDenotation(uint64 size, char *buff, byte minBytes) { if (minBytes <= 1 && size < 126) { - *buff = static_cast(size | 0x80); + *buff = static_cast(size | 0x80); return 1; } else if (minBytes <= 2 && size <= 16382ul) { BE::getBytes(static_cast(size | 0x4000), buff); @@ -474,6 +473,8 @@ byte EbmlElement::makeUInteger(uint64 value, char *buff) * \param value Specifies the value to be written. * \param buff Specifies the buffer to write to. * \param minBytes Specifies the minimum number of bytes to use. + * \remarks Regardless of \a minBytes, this function will never make + * more than 8 bytes. */ byte EbmlElement::makeUInteger(uint64 value, char *buff, byte minBytes) { diff --git a/matroska/matroskaattachment.cpp b/matroska/matroskaattachment.cpp index c259333..63a9baf 100644 --- a/matroska/matroskaattachment.cpp +++ b/matroska/matroskaattachment.cpp @@ -173,7 +173,7 @@ void MatroskaAttachmentMaker::make(ostream &stream, Diagnostics &diag) const if (attachment().data() && attachment().data()->size()) { BE::getBytes(static_cast(MatroskaIds::FileData), buff); stream.write(buff, 2); - len = EbmlElement::makeSizeDenotation(attachment().data()->size(), buff); + len = EbmlElement::makeSizeDenotation(static_cast(attachment().data()->size()), buff); stream.write(buff, len); attachment().data()->copyTo(stream); } diff --git a/matroska/matroskacontainer.cpp b/matroska/matroskacontainer.cpp index 5f0f679..ab4d307 100644 --- a/matroska/matroskacontainer.cpp +++ b/matroska/matroskacontainer.cpp @@ -1579,13 +1579,13 @@ void MatroskaContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFee outputWriter.writeUInt32BE(MatroskaIds::Segment); sizeLength = EbmlElement::makeSizeDenotation(segment.totalDataSize, buff); outputStream.write(buff, sizeLength); - segment.newDataOffset = offset = outputStream.tellp(); // store segment data offset here + segment.newDataOffset = offset = static_cast(outputStream.tellp()); // store segment data offset here // write CRC-32 element ... if (segment.hasCrc32) { // ... if the original element had a CRC-32 element - *buff = EbmlIds::Crc32; - *(buff + 1) = 0x84; // length denotation: 4 byte + *buff = static_cast(EbmlIds::Crc32); + *(buff + 1) = static_cast(0x84); // length denotation: 4 byte // set the value after writing the element crc32Offsets.emplace_back(outputStream.tellp(), segment.totalDataSize); outputStream.write(buff, 6); @@ -1736,16 +1736,16 @@ void MatroskaContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFee switch (level2Element->id()) { case MatroskaIds::Position: // calculate new position - sizeLength = EbmlElement::makeUInteger( - level1Element->startOffset() - segmentData.front().newDataOffset, buff, level2Element->dataSize()); + sizeLength = EbmlElement::makeUInteger(level1Element->startOffset() - segmentData.front().newDataOffset, buff, + level2Element->dataSize() > 8 ? 8 : static_cast(level2Element->dataSize())); // new position can only applied if it doesn't need more bytes than the previous position if (level2Element->dataSize() < sizeLength) { // can't update position -> void position elements ("Position"-elements seem a bit useless anyways) - outputStream.seekp(level2Element->startOffset()); + outputStream.seekp(static_cast(level2Element->startOffset())); outputStream.put(static_cast(EbmlIds::Void)); } else { // update position - outputStream.seekp(level2Element->dataOffset()); + outputStream.seekp(static_cast(level2Element->dataOffset())); outputStream.write(buff, sizeLength); } break; @@ -1754,7 +1754,7 @@ void MatroskaContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFee } } // skip existing "Cluster"-elements - outputStream.seekp(segment.clusterEndOffset); + outputStream.seekp(static_cast(segment.clusterEndOffset)); } progress.updateStep("Writing segment tail ..."); @@ -1847,8 +1847,8 @@ void MatroskaContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFee if (!crc32Offsets.empty()) { progress.updateStep("Updating CRC-32 checksums ..."); for (const auto &crc32Offset : crc32Offsets) { - outputStream.seekg(get<0>(crc32Offset) + 6); - outputStream.seekp(get<0>(crc32Offset) + 2); + outputStream.seekg(static_cast(get<0>(crc32Offset) + 6)); + outputStream.seekp(static_cast(get<0>(crc32Offset) + 2)); writer().writeUInt32LE(reader().readCrc32(get<1>(crc32Offset) - 6)); } } diff --git a/matroska/matroskacues.cpp b/matroska/matroskacues.cpp index 490c9d1..5403cf5 100644 --- a/matroska/matroskacues.cpp +++ b/matroska/matroskacues.cpp @@ -265,7 +265,7 @@ void MatroskaCuePositionUpdater::make(ostream &stream, Diagnostics &diag) break; case MatroskaIds::CuePoint: // write "CuePoint"-element - stream.put(MatroskaIds::CuePoint); + stream.put(static_cast(MatroskaIds::CuePoint)); len = EbmlElement::makeSizeDenotation(m_sizes[cuePointElement], buff); stream.write(buff, len); for (EbmlElement *cuePointChild = cuePointElement->firstChild(); cuePointChild; cuePointChild = cuePointChild->nextSibling()) { @@ -282,7 +282,7 @@ void MatroskaCuePositionUpdater::make(ostream &stream, Diagnostics &diag) break; case MatroskaIds::CueTrackPositions: // write "CueTrackPositions"-element - stream.put(MatroskaIds::CueTrackPositions); + stream.put(static_cast(MatroskaIds::CueTrackPositions)); len = EbmlElement::makeSizeDenotation(m_sizes[cuePointChild], buff); stream.write(buff, len); for (EbmlElement *cueTrackPositionsChild = cuePointChild->firstChild(); cueTrackPositionsChild; @@ -314,7 +314,7 @@ void MatroskaCuePositionUpdater::make(ostream &stream, Diagnostics &diag) break; case MatroskaIds::CueReference: // write "CueReference"-element - stream.put(MatroskaIds::CueRefTime); + stream.put(static_cast(MatroskaIds::CueRefTime)); len = EbmlElement::makeSizeDenotation(m_sizes[cueTrackPositionsChild], buff); stream.write(buff, len); for (EbmlElement *cueReferenceChild = cueTrackPositionsChild->firstChild(); cueReferenceChild; diff --git a/matroska/matroskaseekinfo.cpp b/matroska/matroskaseekinfo.cpp index fbefe4c..189ae5c 100644 --- a/matroska/matroskaseekinfo.cpp +++ b/matroska/matroskaseekinfo.cpp @@ -26,7 +26,11 @@ void MatroskaSeekInfo::shift(uint64 start, int64 amount) { for (auto &info : m_info) { if (get<1>(info) >= start) { - get<1>(info) += amount; + if (amount > 0) { + get<1>(info) += static_cast(amount); + } else { + get<1>(info) -= static_cast(-amount); + } } } } @@ -106,6 +110,8 @@ void MatroskaSeekInfo::parse(EbmlElement *seekHeadElement, Diagnostics &diag) */ void MatroskaSeekInfo::make(ostream &stream, Diagnostics &diag) { + VAR_UNUSED(diag) + uint64 totalSize = 0; char buff0[8]; char buff1[8]; @@ -129,16 +135,16 @@ void MatroskaSeekInfo::make(ostream &stream, Diagnostics &diag) // "Seek" header BE::getBytes(static_cast(MatroskaIds::Seek), buff2); stream.write(buff2, 2); - stream.put(0x80 | (2 + 1 + sizeLength0 + 2 + 1 + sizeLength1)); + stream.put(static_cast(0x80 | (2 + 1 + sizeLength0 + 2 + 1 + sizeLength1))); // "SeekID" element BE::getBytes(static_cast(MatroskaIds::SeekID), buff2); stream.write(buff2, 2); - stream.put(0x80 | sizeLength0); + stream.put(static_cast(0x80 | sizeLength0)); stream.write(buff0, sizeLength0); // "SeekPosition" element BE::getBytes(static_cast(MatroskaIds::SeekPosition), buff2); stream.write(buff2, 2); - stream.put(0x80 | sizeLength1); + stream.put(static_cast(0x80 | sizeLength1)); stream.write(buff1, sizeLength1); } } diff --git a/matroska/matroskatag.cpp b/matroska/matroskatag.cpp index 0c61289..fc8bbfb 100644 --- a/matroska/matroskatag.cpp +++ b/matroska/matroskatag.cpp @@ -111,7 +111,12 @@ void MatroskaTag::parse(EbmlElement &tagElement, Diagnostics &diag) { static const string context("parsing Matroska tag"); tagElement.parse(diag); - m_size = tagElement.totalSize(); + if (tagElement.totalSize() > numeric_limits::max()) { + // FIXME: Support this? Likely not very useful in practise. + diag.emplace_back(DiagLevel::Critical, "Matroska tag is too big.", context); + throw NotImplementedException(); + } + m_size = static_cast(tagElement.totalSize()); for (EbmlElement *child = tagElement.firstChild(); child; child = child->nextSibling()) { child->parse(diag); switch (child->id()) { @@ -292,7 +297,7 @@ void MatroskaTagMaker::make(ostream &stream) const BE::getBytes(static_cast(MatroskaIds::TargetTypeValue), buff); stream.write(buff, 2); len = EbmlElement::makeUInteger(t.level(), buff); - stream.put(0x80 | len); + stream.put(static_cast(0x80 | len)); stream.write(buff, len); } if (!t.levelName().empty()) { @@ -311,7 +316,7 @@ void MatroskaTagMaker::make(ostream &stream) const BE::getBytes(pair.first, buff); for (auto uid : pair.second) { len = EbmlElement::makeUInteger(uid, buff + 3); - *(buff + 2) = 0x80 | len; + *(buff + 2) = static_cast(0x80 | len); stream.write(buff, 3 + len); } } diff --git a/matroska/matroskatagfield.cpp b/matroska/matroskatagfield.cpp index a6c3f98..07848e8 100644 --- a/matroska/matroskatagfield.cpp +++ b/matroska/matroskatagfield.cpp @@ -70,8 +70,8 @@ void MatroskaTagField::reparse(EbmlElement &simpleTagElement, Diagnostics &diag, case MatroskaIds::TagBinary: if (value().isEmpty()) { unique_ptr buffer = make_unique(child->dataSize()); - child->stream().seekg(child->dataOffset()); - child->stream().read(buffer.get(), child->dataSize()); + child->stream().seekg(static_cast(child->dataOffset())); + child->stream().read(buffer.get(), static_cast(child->dataSize())); switch (child->id()) { case MatroskaIds::TagString: value().assignData(move(buffer), child->dataSize(), TagDataType::Text, TagTextEncoding::Utf8); diff --git a/matroska/matroskatrack.cpp b/matroska/matroskatrack.cpp index 253d360..f96be62 100644 --- a/matroska/matroskatrack.cpp +++ b/matroska/matroskatrack.cpp @@ -442,13 +442,13 @@ void MatroskaTrack::internalParseHeader(Diagnostics &diag) } // read further information from the CodecPrivate element for some codecs + EbmlElement *codecPrivateElement; switch (m_format.general) { - EbmlElement *codecPrivateElement; case GeneralMediaFormat::MicrosoftVideoCodecManager: if ((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate, diag))) { // parse bitmap info header to determine actual format if (codecPrivateElement->dataSize() >= 0x28) { - m_istream->seekg(codecPrivateElement->dataOffset()); + m_istream->seekg(static_cast(codecPrivateElement->dataOffset())); BitmapInfoHeader bitmapInfoHeader; bitmapInfoHeader.parse(reader()); m_formatId.reserve(m_formatId.size() + 7); @@ -465,7 +465,7 @@ void MatroskaTrack::internalParseHeader(Diagnostics &diag) if ((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate, diag))) { // parse WAVE header to determine actual format if (codecPrivateElement->dataSize() >= 16) { - m_istream->seekg(codecPrivateElement->dataOffset()); + m_istream->seekg(static_cast(codecPrivateElement->dataOffset())); WaveFormatHeader waveFormatHeader; waveFormatHeader.parse(reader()); WaveAudioStream::addInfo(waveFormatHeader, *this); @@ -502,7 +502,7 @@ void MatroskaTrack::internalParseHeader(Diagnostics &diag) if ((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate, diag))) { auto avcConfig = make_unique(); try { - m_istream->seekg(codecPrivateElement->dataOffset()); + m_istream->seekg(static_cast(codecPrivateElement->dataOffset())); avcConfig->parse(m_reader, codecPrivateElement->dataSize()); Mp4Track::addInfo(*avcConfig, *this); } catch (const TruncatedDataException &) { diff --git a/mediaformat.cpp b/mediaformat.cpp index c33858f..11877c8 100644 --- a/mediaformat.cpp +++ b/mediaformat.cpp @@ -1005,9 +1005,8 @@ const char *mediaTypeName(MediaType mediaType) return "Control"; case MediaType::Unknown: return "Other"; - default: - return ""; } + return ""; } } // namespace TagParser diff --git a/mp4/mp4atom.cpp b/mp4/mp4atom.cpp index 9718b5c..fdbe1f8 100644 --- a/mp4/mp4atom.cpp +++ b/mp4/mp4atom.cpp @@ -68,7 +68,7 @@ void Mp4Atom::internalParse(Diagnostics &diag) context); throw TruncatedDataException(); } - stream().seekg(startOffset()); + stream().seekg(static_cast(startOffset())); m_dataSize = reader().readUInt32BE(); if (m_dataSize == 0) { // atom size extends to rest of the file/enclosing container @@ -122,6 +122,11 @@ void Mp4Atom::internalParse(Diagnostics &diag) * \brief This function helps to write the atom size after writing an atom to a stream. * \param stream Specifies the stream. * \param startOffset Specifies the start offset of the atom. + * \remarks The caller must ensure that no seek before \a startOffset happended. + * \throw The caller has to be sure, that the number of written bytes does not exceed + * maximum of an 32-bit unsigned integer. Otherwise the function will throw + * Failure and Mp4Atom::seekBackAndWriteAtomSize64 should be used instead. + * \todo Add a version which creates a diag message (in addition to throwing an exception). * * This function seeks back to the start offset and writes the difference between the * previous offset and the start offset as 32-bit unsigned integer to the \a stream. @@ -130,9 +135,13 @@ void Mp4Atom::internalParse(Diagnostics &diag) void Mp4Atom::seekBackAndWriteAtomSize(std::ostream &stream, const ostream::pos_type &startOffset) { ostream::pos_type currentOffset = stream.tellp(); + const auto atomSize(currentOffset - startOffset); + if (atomSize > numeric_limits::max()) { + throw Failure(); + } stream.seekp(startOffset); BinaryWriter writer(&stream); - writer.writeUInt32BE(currentOffset - startOffset); + writer.writeUInt32BE(static_cast(atomSize)); stream.seekp(currentOffset); } @@ -140,6 +149,7 @@ void Mp4Atom::seekBackAndWriteAtomSize(std::ostream &stream, const ostream::pos_ * \brief This function helps to write the atom size after writing an atom to a stream. * \param stream Specifies the stream. * \param startOffset Specifies the start offset of the atom. + * \remarks The caller must ensure that no seek before \a startOffset happended. * * This function seeks back to the start offset and writes the difference between the * previous offset and the start offset as 64-bit unsigned integer to the \a stream. @@ -152,7 +162,7 @@ void Mp4Atom::seekBackAndWriteAtomSize64(std::ostream &stream, const ostream::po BinaryWriter writer(&stream); writer.writeUInt32BE(1); stream.seekp(4, ios_base::cur); - writer.writeUInt64BE(currentOffset - startOffset); + writer.writeUInt64BE(static_cast(currentOffset - startOffset)); stream.seekp(currentOffset); } diff --git a/mp4/mp4container.cpp b/mp4/mp4container.cpp index 4a403a6..f6e4665 100644 --- a/mp4/mp4container.cpp +++ b/mp4/mp4container.cpp @@ -644,8 +644,8 @@ calculatePadding: // write padding if (newPadding) { // write free atom header - if (newPadding < 0xFFFFFFFF) { - outputWriter.writeUInt32BE(newPadding); + if (newPadding < numeric_limits::max()) { + outputWriter.writeUInt32BE(static_cast(newPadding)); outputWriter.writeUInt32BE(Mp4AtomIds::Free); newPadding -= 8; } else { @@ -678,7 +678,7 @@ calculatePadding: break; } else { // store media data offsets when not writing chunk-by-chunk to be able to update chunk offset table - origMediaDataOffsets.push_back(level0Atom->startOffset()); + origMediaDataOffsets.push_back(static_cast(level0Atom->startOffset())); newMediaDataOffsets.push_back(outputStream.tellp()); } FALLTHROUGH; @@ -741,8 +741,8 @@ calculatePadding: // still chunks to be copied (of this track)? if (chunkIndexWithinTrack < chunkOffsetTable.size() && chunkIndexWithinTrack < chunkSizesTable.size()) { // copy chunk, update entry in chunk offset table - sourceStream.seekg(chunkOffsetTable[chunkIndexWithinTrack]); - chunkOffsetTable[chunkIndexWithinTrack] = outputStream.tellp(); + sourceStream.seekg(static_cast(chunkOffsetTable[chunkIndexWithinTrack])); + chunkOffsetTable[chunkIndexWithinTrack] = static_cast(outputStream.tellp()); copyHelper.copy(sourceStream, outputStream, chunkSizesTable[chunkIndexWithinTrack]); // update counter / status @@ -916,12 +916,13 @@ void Mp4Container::updateOffsets(const std::vector &oldMdatOffsets, const uint64 off = reader().readUInt64BE(); for (auto iOld = oldMdatOffsets.cbegin(), iNew = newMdatOffsets.cbegin(), end = oldMdatOffsets.cend(); iOld != end; ++iOld, ++iNew) { - if (off >= static_cast(*iOld)) { - off += (*iNew - *iOld); - stream().seekp(static_cast(tfhdAtom->dataOffset()) + 8); - writer().writeUInt64BE(off); - break; + if (off < static_cast(*iOld)) { + continue; } + off += static_cast(*iNew - *iOld); + stream().seekp(static_cast(tfhdAtom->dataOffset()) + 8); + writer().writeUInt64BE(off); + break; } } switch (tfhdAtomCount) { diff --git a/mp4/mp4tag.cpp b/mp4/mp4tag.cpp index 38c2226..64b1366 100644 --- a/mp4/mp4tag.cpp +++ b/mp4/mp4tag.cpp @@ -27,10 +27,12 @@ Mp4ExtendedFieldId::Mp4ExtendedFieldId(KnownField field) { switch (field) { case KnownField::EncoderSettings: - mean = Mp4TagExtendedMeanIds::iTunes, name = Mp4TagExtendedNameIds::cdec; + mean = Mp4TagExtendedMeanIds::iTunes; + name = Mp4TagExtendedNameIds::cdec; break; case KnownField::RecordLabel: - mean = Mp4TagExtendedMeanIds::iTunes, name = Mp4TagExtendedNameIds::label; + mean = Mp4TagExtendedMeanIds::iTunes; + name = Mp4TagExtendedNameIds::label; updateOnly = true; // set record label via extended field only if extended field is already present break; default: @@ -319,7 +321,11 @@ void Mp4Tag::parse(Mp4Atom &metaAtom, Diagnostics &diag) static const string context("parsing MP4 tag"); istream &stream = metaAtom.container().stream(); BinaryReader &reader = metaAtom.container().reader(); - m_size = metaAtom.totalSize(); + if (metaAtom.totalSize() > numeric_limits::max()) { + diag.emplace_back(DiagLevel::Critical, "Can't handle such big \"meta\" atoms.", context); + throw NotImplementedException(); + } + m_size = static_cast(metaAtom.totalSize()); Mp4Atom *subAtom = nullptr; try { metaAtom.childById(Mp4AtomIds::HandlerReference, diag); @@ -327,7 +333,7 @@ void Mp4Tag::parse(Mp4Atom &metaAtom, Diagnostics &diag) diag.emplace_back(DiagLevel::Critical, "Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context); } if (subAtom) { - stream.seekg(subAtom->startOffset() + subAtom->headerSize()); + stream.seekg(static_cast(subAtom->startOffset() + subAtom->headerSize())); int versionByte = reader.readByte(); if (versionByte != 0) { diag.emplace_back(DiagLevel::Warning, "Version is unknown.", context); @@ -351,20 +357,19 @@ void Mp4Tag::parse(Mp4Atom &metaAtom, Diagnostics &diag) } catch (const Failure &) { diag.emplace_back(DiagLevel::Critical, "Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context); } - if (subAtom) { - for (auto *child = subAtom->firstChild(); child; child = child->nextSibling()) { - Mp4TagField tagField; - try { - child->parse(diag); - tagField.reparse(*child, diag); - fields().emplace(child->id(), move(tagField)); - } catch (const Failure &) { - } - } - } else { + if (!subAtom) { diag.emplace_back(DiagLevel::Warning, "No ilst atom found (stores attached meta information).", context); throw NoDataFoundException(); } + for (auto *child = subAtom->firstChild(); child; child = child->nextSibling()) { + Mp4TagField tagField; + try { + child->parse(diag); + tagField.reparse(*child, diag); + fields().emplace(child->id(), move(tagField)); + } catch (const Failure &) { + } + } } /*! @@ -429,6 +434,10 @@ Mp4TagMaker::Mp4TagMaker(Mp4Tag &tag, Diagnostics &diag) if (m_ilstSize != 8) { m_metaSize += m_ilstSize; } + if (m_metaSize >= numeric_limits::max()) { + diag.emplace_back(DiagLevel::Critical, "Making such big tags is not implemented.", "making MP4 tag"); + throw NotImplementedException(); + } } /*! @@ -442,7 +451,7 @@ void Mp4TagMaker::make(ostream &stream, Diagnostics &diag) { // write meta head BinaryWriter writer(&stream); - writer.writeUInt32BE(m_metaSize); + writer.writeUInt32BE(static_cast(m_metaSize)); writer.writeUInt32BE(Mp4AtomIds::Meta); // write hdlr atom static const byte hdlrData[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -450,7 +459,7 @@ void Mp4TagMaker::make(ostream &stream, Diagnostics &diag) stream.write(reinterpret_cast(hdlrData), sizeof(hdlrData)); if (m_ilstSize != 8) { // write ilst head - writer.writeUInt32BE(m_ilstSize); + writer.writeUInt32BE(static_cast(m_ilstSize)); writer.writeUInt32BE(Mp4AtomIds::ItunesList); // write fields for (auto &maker : m_maker) { diff --git a/mp4/mp4tagfield.cpp b/mp4/mp4tagfield.cpp index bed847f..8f36d87 100644 --- a/mp4/mp4tagfield.cpp +++ b/mp4/mp4tagfield.cpp @@ -98,7 +98,7 @@ void Mp4TagField::reparse(Mp4Atom &ilstChild, Diagnostics &diag) } continue; } - stream.seekg(dataAtom->dataOffset()); + stream.seekg(static_cast(dataAtom->dataOffset())); if (reader.readByte() != 0) { diag.emplace_back(DiagLevel::Warning, "The version indicator byte is not zero, the tag atom might be unsupported and hence not be parsed correctly.", context); @@ -117,7 +117,7 @@ void Mp4TagField::reparse(Mp4Atom &ilstChild, Diagnostics &diag) switch (m_parsedRawDataType) { case RawDataType::Utf8: case RawDataType::Utf16: - stream.seekg(dataAtom->dataOffset() + 8); + stream.seekg(static_cast(dataAtom->dataOffset() + 8)); value().assignText(reader.readString(dataAtom->dataSize() - 8), (m_parsedRawDataType == RawDataType::Utf16) ? TagTextEncoding::Utf16BigEndian : TagTextEncoding::Utf8); break; @@ -140,10 +140,10 @@ void Mp4TagField::reparse(Mp4Atom &ilstChild, Diagnostics &diag) break; default:; } - const streamsize coverSize = dataAtom->dataSize() - 8; - unique_ptr coverData = make_unique(coverSize); + const auto coverSize = static_cast(dataAtom->dataSize() - 8); + auto coverData = make_unique(static_cast(coverSize)); stream.read(coverData.get(), coverSize); - value().assignData(move(coverData), coverSize, TagDataType::Picture); + value().assignData(move(coverData), static_cast(coverSize), TagDataType::Picture); break; } case RawDataType::BeSignedInt: { @@ -215,13 +215,13 @@ void Mp4TagField::reparse(Mp4Atom &ilstChild, Diagnostics &diag) } break; default: // no supported data type, read raw data - streamsize dataSize = dataAtom->dataSize() - 8; - unique_ptr data = make_unique(dataSize); + const auto dataSize = static_cast(dataAtom->dataSize() - 8); + auto data = make_unique(static_cast(dataSize)); stream.read(data.get(), dataSize); if (ilstChild.id() == Mp4TagAtomIds::Cover) { - value().assignData(move(data), dataSize, TagDataType::Picture); + value().assignData(move(data), static_cast(dataSize), TagDataType::Picture); } else { - value().assignData(move(data), dataSize, TagDataType::Undefined); + value().assignData(move(data), static_cast(dataSize), TagDataType::Undefined); } } } @@ -237,7 +237,7 @@ void Mp4TagField::reparse(Mp4Atom &ilstChild, Diagnostics &diag) } continue; } - stream.seekg(dataAtom->dataOffset() + 4); + stream.seekg(static_cast(dataAtom->dataOffset() + 4)); m_mean = reader.readString(dataAtom->dataSize() - 4); } else if (dataAtom->id() == Mp4AtomIds::Name) { if (dataAtom->dataSize() < 4) { @@ -251,7 +251,7 @@ void Mp4TagField::reparse(Mp4Atom &ilstChild, Diagnostics &diag) } continue; } - stream.seekg(dataAtom->dataOffset() + 4); + stream.seekg(static_cast(dataAtom->dataOffset() + 4)); m_name = reader.readString(dataAtom->dataSize() - 4); } else { diag.emplace_back(DiagLevel::Warning, @@ -501,10 +501,10 @@ Mp4TagFieldMaker::Mp4TagFieldMaker(Mp4TagField &field, Diagnostics &diag) if (number <= numeric_limits::max() && number >= numeric_limits::min()) { m_writer.writeUInt16BE(static_cast(number)); } else if (number > 0) { - m_writer.writeUInt32BE(number); + m_writer.writeUInt32BE(static_cast(number)); } else { throw ConversionException( - "Negative integer can not be assigned to the field with the id \"" % interpretIntegerAsString(m_field.id()) + "\"."); + "Negative integer can not be assigned to the field with the ID \"" % interpretIntegerAsString(m_field.id()) + "\"."); } break; } @@ -531,7 +531,7 @@ Mp4TagFieldMaker::Mp4TagFieldMaker(Mp4TagField &field, Diagnostics &diag) break; } case Mp4TagAtomIds::PreDefinedGenre: - m_writer.writeUInt16BE(m_field.value().toStandardGenreIndex()); + m_writer.writeUInt16BE(static_cast(m_field.value().toStandardGenreIndex())); break; default:; // leave converted data empty to write original data later } @@ -553,6 +553,10 @@ Mp4TagFieldMaker::Mp4TagFieldMaker(Mp4TagField &field, Diagnostics &diag) m_totalSize = 8 // calculate entire size + (m_field.name().empty() ? 0 : (12 + m_field.name().length())) + (m_field.mean().empty() ? 0 : (12 + m_field.mean().length())) + (m_dataSize ? (16 + m_dataSize) : 0); + if (m_totalSize > numeric_limits::max()) { + diag.emplace_back(DiagLevel::Critical, "Making a such big MP4 tag field is not supported.", context); + throw NotImplementedException(); + } } /*! @@ -566,25 +570,25 @@ void Mp4TagFieldMaker::make(ostream &stream) { m_writer.setStream(&stream); // size of entire tag atom - m_writer.writeUInt32BE(m_totalSize); + m_writer.writeUInt32BE(static_cast(m_totalSize)); // id of tag atom m_writer.writeUInt32BE(m_field.id()); if (!m_field.mean().empty()) { // write "mean" - m_writer.writeUInt32BE(12 + m_field.mean().size()); + m_writer.writeUInt32BE(static_cast(12 + m_field.mean().size())); m_writer.writeUInt32BE(Mp4AtomIds::Mean); m_writer.writeUInt32BE(0); m_writer.writeString(m_field.mean()); } if (!m_field.name().empty()) { // write "name" - m_writer.writeUInt32BE(12 + m_field.name().length()); + m_writer.writeUInt32BE(static_cast(12 + m_field.name().length())); m_writer.writeUInt32BE(Mp4AtomIds::Name); m_writer.writeUInt32BE(0); m_writer.writeString(m_field.name()); } if (!m_field.value().isEmpty()) { // write data - m_writer.writeUInt32BE(16 + m_dataSize); // size of data atom + m_writer.writeUInt32BE(static_cast(16 + m_dataSize)); // size of data atom m_writer.writeUInt32BE(Mp4AtomIds::Data); // id of data atom m_writer.writeByte(0); // version m_writer.writeUInt24BE(m_rawDataType); @@ -595,7 +599,7 @@ void Mp4TagFieldMaker::make(ostream &stream) stream << m_convertedData.rdbuf(); } else { // no conversion was needed, write data directly from tag value - stream.write(m_field.value().dataPointer(), m_field.value().dataSize()); + stream.write(m_field.value().dataPointer(), static_cast(m_field.value().dataSize())); } } } diff --git a/mp4/mp4track.cpp b/mp4/mp4track.cpp index 92cc206..a4b89bd 100644 --- a/mp4/mp4track.cpp +++ b/mp4/mp4track.cpp @@ -1219,8 +1219,8 @@ void Mp4Track::makeTrackHeader(Diagnostics &diag) // make further values, either from existing tkhd atom or just some defaults if (info.canUseExisting) { // write all bytes after the previously determined additionalDataOffset - m_ostream->write( - m_tkhdAtom->buffer().get() + m_tkhdAtom->headerSize() + info.additionalDataOffset, m_tkhdAtom->dataSize() - info.additionalDataOffset); + m_ostream->write(m_tkhdAtom->buffer().get() + m_tkhdAtom->headerSize() + info.additionalDataOffset, + static_cast(m_tkhdAtom->dataSize() - info.additionalDataOffset)); // discard the buffer again if it wasn't present before if (info.discardBuffer) { m_tkhdAtom->discardBuffer(); diff --git a/mp4/mpeg4descriptor.cpp b/mp4/mpeg4descriptor.cpp index c826a7b..57549fe 100644 --- a/mp4/mpeg4descriptor.cpp +++ b/mp4/mpeg4descriptor.cpp @@ -62,7 +62,7 @@ void Mpeg4Descriptor::internalParse(Diagnostics &diag) "parsing MPEG-4 descriptor"); throw TruncatedDataException(); } - stream().seekg(startOffset()); + stream().seekg(static_cast(startOffset())); // read ID m_idLength = m_sizeLength = 1; m_id = reader().readByte(); @@ -76,18 +76,20 @@ void Mpeg4Descriptor::internalParse(Diagnostics &diag) // check whether the denoted data size exceeds the available data size if (maxTotalSize() < totalSize()) { diag.emplace_back(DiagLevel::Warning, "The descriptor seems to be truncated; unable to parse siblings of that ", parsingContext()); - m_dataSize = maxTotalSize(); // using max size instead + m_dataSize = static_cast(maxTotalSize()); // using max size instead } m_firstChild.reset(); - Mpeg4Descriptor *sibling = nullptr; - if (totalSize() < maxTotalSize()) { - if (parent()) { - sibling = new Mpeg4Descriptor(*(parent()), startOffset() + totalSize()); - } else { - sibling = new Mpeg4Descriptor(container(), startOffset() + totalSize(), maxTotalSize() - totalSize()); - } + + // check for siblings + if (totalSize() >= maxTotalSize()) { + m_nextSibling.reset(); + return; + } + if (parent()) { + m_nextSibling.reset(new Mpeg4Descriptor(*(parent()), startOffset() + totalSize())); + } else { + m_nextSibling.reset(new Mpeg4Descriptor(container(), startOffset() + totalSize(), maxTotalSize() - totalSize())); } - m_nextSibling.reset(sibling); } } // namespace TagParser diff --git a/mpegaudio/mpegaudioframestream.cpp b/mpegaudio/mpegaudioframestream.cpp index 4a6e4cd..8c65966 100644 --- a/mpegaudio/mpegaudioframestream.cpp +++ b/mpegaudio/mpegaudioframestream.cpp @@ -23,7 +23,7 @@ namespace TagParser { void MpegAudioFrameStream::addInfo(const MpegAudioFrame &frame, AbstractTrack &track) { track.m_version = frame.mpegVersion(); - track.m_format = MediaFormat(GeneralMediaFormat::Mpeg1Audio, frame.layer()); + track.m_format = MediaFormat(GeneralMediaFormat::Mpeg1Audio, static_cast(frame.layer())); track.m_channelCount = frame.channelMode() == MpegChannelMode::SingleChannel ? 1 : 2; track.m_channelConfig = static_cast(frame.channelMode()); track.m_samplingFrequency = frame.samplingFrequency(); @@ -42,7 +42,7 @@ void MpegAudioFrameStream::internalParseHeader(Diagnostics &diag) } else { m_size = static_cast(m_istream->tellg()) + 125u - m_startOffset; } - m_istream->seekg(m_startOffset, ios_base::beg); + m_istream->seekg(static_cast(m_startOffset), ios_base::beg); // parse frame header m_frames.emplace_back(); MpegAudioFrame &frame = m_frames.back(); @@ -60,7 +60,7 @@ void MpegAudioFrameStream::internalParseHeader(Diagnostics &diag) ? ((static_cast(m_size) * 8.0) / (static_cast(frame.xingFrameCount() * frame.sampleCount()) / static_cast(frame.samplingFrequency())) / 1024.0) : frame.bitrate(); - m_duration = TimeSpan::fromSeconds(static_cast(m_size) / (m_bytesPerSecond = m_bitrate * 125)); + m_duration = TimeSpan::fromSeconds(static_cast(m_size) / (m_bytesPerSecond = static_cast(m_bitrate * 125))); } } // namespace TagParser diff --git a/ogg/oggcontainer.cpp b/ogg/oggcontainer.cpp index 7864623..424cce4 100644 --- a/ogg/oggcontainer.cpp +++ b/ogg/oggcontainer.cpp @@ -112,6 +112,7 @@ OggVorbisComment *OggContainer::createTag(const TagTarget &target) } else { // TODO: error handling? } + break; default:; } // TODO: allow adding tags to FLAC tracks (not really important, because a tag should always be present) @@ -349,7 +350,7 @@ void OggContainer::makeVorbisCommentSegment(stringstream &buffer, CopyHelper<653 comment->make(buffer, VorbisCommentFlags::NoSignature | VorbisCommentFlags::NoFramingByte, diag); // finally make the header - header.setDataSize(buffer.tellp() - offset - 4); + header.setDataSize(static_cast(buffer.tellp() - offset - 4)); if (header.dataSize() > 0xFFFFFF) { diag.emplace_back( DiagLevel::Critical, "Size of Vorbis comment exceeds size limit for FLAC \"METADATA_BLOCK_HEADER\".", "making Vorbis Comment"); @@ -361,7 +362,7 @@ void OggContainer::makeVorbisCommentSegment(stringstream &buffer, CopyHelper<653 } default:; } - newSegmentSizes.push_back(buffer.tellp() - offset); + newSegmentSizes.push_back(static_cast(buffer.tellp() - offset)); } void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback &progress) @@ -430,51 +431,52 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback uint64 segmentOffset = m_iterator.currentSegmentOffset(); vector::size_type segmentIndex = 0; for (const auto segmentSize : currentPage.segmentSizes()) { - if (segmentSize) { - // check whether this segment contains the Vorbis Comment - if ((m_iterator.currentPageIndex() >= currentParams->firstPageIndex && segmentIndex >= currentParams->firstSegmentIndex) - && (m_iterator.currentPageIndex() <= currentParams->lastPageIndex && segmentIndex <= currentParams->lastSegmentIndex)) { - // prevent making the comment twice if it spreads over multiple pages/segments - if (!currentParams->removed - && ((m_iterator.currentPageIndex() == currentParams->firstPageIndex - && m_iterator.currentSegmentIndex() == currentParams->firstSegmentIndex))) { - makeVorbisCommentSegment(buffer, copyHelper, newSegmentSizes, currentComment, currentParams, diag); - } + if (!segmentSize) { + ++segmentIndex; + continue; + } + // check whether this segment contains the Vorbis Comment + if ((m_iterator.currentPageIndex() >= currentParams->firstPageIndex && segmentIndex >= currentParams->firstSegmentIndex) + && (m_iterator.currentPageIndex() <= currentParams->lastPageIndex && segmentIndex <= currentParams->lastSegmentIndex)) { + // prevent making the comment twice if it spreads over multiple pages/segments + if (!currentParams->removed + && ((m_iterator.currentPageIndex() == currentParams->firstPageIndex + && m_iterator.currentSegmentIndex() == currentParams->firstSegmentIndex))) { + makeVorbisCommentSegment(buffer, copyHelper, newSegmentSizes, currentComment, currentParams, diag); + } - // proceed with next comment? - if (m_iterator.currentPageIndex() > currentParams->lastPageIndex - || (m_iterator.currentPageIndex() == currentParams->lastPageIndex - && segmentIndex > currentParams->lastSegmentIndex)) { - if (++tagIterator != tagEnd) { - currentParams = &(currentComment = tagIterator->get())->oggParams(); - } else { - currentComment = nullptr; - currentParams = nullptr; - } - } - } else { - // copy other segments unchanged - backupStream.seekg(segmentOffset); - copyHelper.copy(backupStream, buffer, segmentSize); - newSegmentSizes.push_back(segmentSize); - - // check whether there is a new comment to be inserted into the current page - if (m_iterator.currentPageIndex() == currentParams->lastPageIndex - && currentParams->firstSegmentIndex == numeric_limits::max()) { - if (!currentParams->removed) { - makeVorbisCommentSegment(buffer, copyHelper, newSegmentSizes, currentComment, currentParams, diag); - } - // proceed with next comment - if (++tagIterator != tagEnd) { - currentParams = &(currentComment = tagIterator->get())->oggParams(); - } else { - currentComment = nullptr; - currentParams = nullptr; - } + // proceed with next comment? + if (m_iterator.currentPageIndex() > currentParams->lastPageIndex + || (m_iterator.currentPageIndex() == currentParams->lastPageIndex && segmentIndex > currentParams->lastSegmentIndex)) { + if (++tagIterator != tagEnd) { + currentParams = &(currentComment = tagIterator->get())->oggParams(); + } else { + currentComment = nullptr; + currentParams = nullptr; + } + } + } else { + // copy other segments unchanged + backupStream.seekg(static_cast(segmentOffset)); + copyHelper.copy(backupStream, buffer, segmentSize); + newSegmentSizes.push_back(segmentSize); + + // check whether there is a new comment to be inserted into the current page + if (m_iterator.currentPageIndex() == currentParams->lastPageIndex + && currentParams->firstSegmentIndex == numeric_limits::max()) { + if (!currentParams->removed) { + makeVorbisCommentSegment(buffer, copyHelper, newSegmentSizes, currentComment, currentParams, diag); + } + // proceed with next comment + if (++tagIterator != tagEnd) { + currentParams = &(currentComment = tagIterator->get())->oggParams(); + } else { + currentComment = nullptr; + currentParams = nullptr; } } - segmentOffset += segmentSize; } + segmentOffset += segmentSize; ++segmentIndex; } @@ -486,12 +488,12 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback // write pages until all data in the buffer is written while (newSegmentSizesIterator != newSegmentSizesEnd) { // write header - backupStream.seekg(currentPage.startOffset()); - updatedPageOffsets.push_back(stream().tellp()); // memorize offset to update checksum later + backupStream.seekg(static_cast(currentPage.startOffset())); + updatedPageOffsets.push_back(static_cast(stream().tellp())); // memorize offset to update checksum later copyHelper.copy(backupStream, stream(), 27); // just copy header from original file // set continue flag stream().seekp(-22, ios_base::cur); - stream().put(currentPage.headerTypeFlag() & (continuePreviousSegment ? 0xFF : 0xFE)); + stream().put(static_cast(currentPage.headerTypeFlag() & (continuePreviousSegment ? 0xFF : 0xFE))); continuePreviousSegment = true; // adjust page sequence number stream().seekp(12, ios_base::cur); @@ -503,14 +505,14 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback uint32 currentSize = 0; while (bytesLeft && segmentSizesWritten < 0xFF) { while (bytesLeft >= 0xFF && segmentSizesWritten < 0xFF) { - stream().put(0xFF); + stream().put(static_cast(0xFF)); currentSize += 0xFF; bytesLeft -= 0xFF; ++segmentSizesWritten; } if (bytesLeft && segmentSizesWritten < 0xFF) { // bytes left is here < 0xFF - stream().put(bytesLeft); + stream().put(static_cast(bytesLeft)); currentSize += bytesLeft; bytesLeft = 0; ++segmentSizesWritten; @@ -534,7 +536,7 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback // -> write segment table size (segmentSizesWritten) and segment data // -> seek back and write updated page segment number stream().seekp(-1 - segmentSizesWritten, ios_base::cur); - stream().put(segmentSizesWritten); + stream().put(static_cast(segmentSizesWritten)); stream().seekp(segmentSizesWritten, ios_base::cur); // -> write actual page data copyHelper.copy(buffer, stream(), currentSize); @@ -546,8 +548,8 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback } else { if (pageSequenceNumber != m_iterator.currentPageIndex()) { // just update page sequence number - backupStream.seekg(currentPage.startOffset()); - updatedPageOffsets.push_back(stream().tellp()); // memorize offset to update checksum later + backupStream.seekg(static_cast(currentPage.startOffset())); + updatedPageOffsets.push_back(static_cast(stream().tellp())); // memorize offset to update checksum later copyHelper.copy(backupStream, stream(), 27); stream().seekp(-9, ios_base::cur); writer().writeUInt32LE(pageSequenceNumber); @@ -555,7 +557,7 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback copyHelper.copy(backupStream, stream(), pageSize - 27); } else { // copy page unchanged - backupStream.seekg(currentPage.startOffset()); + backupStream.seekg(static_cast(currentPage.startOffset())); copyHelper.copy(backupStream, stream(), pageSize); } ++pageSequenceNumber; @@ -563,7 +565,7 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback } // report new size - fileInfo().reportSizeChanged(stream().tellp()); + fileInfo().reportSizeChanged(static_cast(stream().tellp())); // "save as path" is now the regular path if (!fileInfo().saveFilePath().empty()) { diff --git a/ogg/oggiterator.cpp b/ogg/oggiterator.cpp index 0e67ca8..9b1261c 100644 --- a/ogg/oggiterator.cpp +++ b/ogg/oggiterator.cpp @@ -136,9 +136,9 @@ void OggIterator::read(char *buffer, size_t count) size_t bytesRead = 0; while (*this && count) { const uint32 available = currentSegmentSize() - m_bytesRead; - stream().seekg(currentCharacterOffset()); + stream().seekg(static_cast(currentCharacterOffset())); if (count <= available) { - stream().read(buffer + bytesRead, count); + stream().read(buffer + bytesRead, static_cast(count)); m_bytesRead += count; return; } else { @@ -171,9 +171,9 @@ size_t OggIterator::readAll(char *buffer, size_t max) size_t bytesRead = 0; while (*this && max) { const uint32 available = currentSegmentSize() - m_bytesRead; - stream().seekg(currentCharacterOffset()); + stream().seekg(static_cast(currentCharacterOffset())); if (max <= available) { - stream().read(buffer + bytesRead, max); + stream().read(buffer + bytesRead, static_cast(max)); m_bytesRead += max; return bytesRead + max; } else { @@ -243,7 +243,7 @@ bool OggIterator::resyncAt(uint64 offset) } // find capture pattern 'OggS' - stream().seekg(offset); + stream().seekg(static_cast(offset)); byte lettersFound = 0; for (uint64 bytesAvailable = max(streamSize() - offset, 65307ul); bytesAvailable >= 27; --bytesAvailable) { switch (static_cast(stream().get())) { diff --git a/ogg/oggpage.cpp b/ogg/oggpage.cpp index 9941535..96e4375 100644 --- a/ogg/oggpage.cpp +++ b/ogg/oggpage.cpp @@ -25,7 +25,7 @@ namespace TagParser { void OggPage::parseHeader(istream &stream, uint64 startOffset, int32 maxSize) { // prepare reading - stream.seekg(startOffset); + stream.seekg(static_cast(startOffset)); BinaryReader reader(&stream); if (maxSize < 27) { throw TruncatedDataException(); @@ -74,7 +74,7 @@ void OggPage::parseHeader(istream &stream, uint64 startOffset, int32 maxSize) */ uint32 OggPage::computeChecksum(istream &stream, uint64 startOffset) { - stream.seekg(startOffset); + stream.seekg(static_cast(startOffset)); uint32 crc = 0x0; byte value, segmentTableSize = 0, segmentTableIndex = 0; for (uint32 i = 0, segmentLength = 27; i != segmentLength; ++i) { @@ -82,6 +82,7 @@ uint32 OggPage::computeChecksum(istream &stream, uint64 startOffset) case 22: // bytes 22, 23, 24, 25 hold denoted checksum and must be set to zero stream.seekg(4, ios_base::cur); + FALLTHROUGH; case 23: case 24: case 25: @@ -89,10 +90,10 @@ uint32 OggPage::computeChecksum(istream &stream, uint64 startOffset) break; case 26: // byte 26 holds the number of segment sizes - segmentLength += (segmentTableSize = (value = stream.get())); + segmentLength += (segmentTableSize = (value = static_cast(stream.get()))); break; default: - value = stream.get(); + value = static_cast(stream.get()); if (i > 26 && segmentTableIndex < segmentTableSize) { // bytes 27 to (27 + segment size count) hold page size segmentLength += value; @@ -112,7 +113,7 @@ void OggPage::updateChecksum(iostream &stream, uint64 startOffset) { char buff[4]; LE::getBytes(computeChecksum(stream, startOffset), buff); - stream.seekp(startOffset + 22); + stream.seekp(static_cast(startOffset + 22)); stream.write(buff, sizeof(buff)); } @@ -124,11 +125,11 @@ uint32 OggPage::makeSegmentSizeDenotation(ostream &stream, uint32 size) { uint32 bytesWritten = 1; while (size >= 0xff) { - stream.put(0xff); + stream.put(static_cast(0xff)); size -= 0xff; ++bytesWritten; } - stream.put(size); + stream.put(static_cast(size)); return bytesWritten; } diff --git a/ogg/oggstream.cpp b/ogg/oggstream.cpp index 00e8613..028ab7c 100644 --- a/ogg/oggstream.cpp +++ b/ogg/oggstream.cpp @@ -65,7 +65,7 @@ void OggStream::internalParseHeader(Diagnostics &diag) const uint32 currentSize = iterator.currentSegmentSize(); if (currentSize >= 8) { // determine stream format - inputStream().seekg(iterator.currentSegmentOffset()); + inputStream().seekg(static_cast(iterator.currentSegmentOffset())); const uint64 sig = reader().readUInt64BE(); if ((sig & 0x00ffffffffffff00u) == 0x00766F7262697300u) { diff --git a/tagvalue.cpp b/tagvalue.cpp index 26bafb3..14057a8 100644 --- a/tagvalue.cpp +++ b/tagvalue.cpp @@ -77,21 +77,22 @@ TagValue::TagValue(const TagValue &other) */ TagValue &TagValue::operator=(const TagValue &other) { - if (this != &other) { - m_size = other.m_size; - m_type = other.m_type; - m_desc = other.m_desc; - m_mimeType = other.m_mimeType; - m_language = other.m_language; - m_labeledAsReadonly = other.m_labeledAsReadonly; - m_encoding = other.m_encoding; - m_descEncoding = other.m_descEncoding; - if (other.isEmpty()) { - m_ptr.reset(); - } else { - m_ptr = make_unique(m_size); - std::copy(other.m_ptr.get(), other.m_ptr.get() + other.m_size, m_ptr.get()); - } + if (this == &other) { + return *this; + } + m_size = other.m_size; + m_type = other.m_type; + m_desc = other.m_desc; + m_mimeType = other.m_mimeType; + m_language = other.m_language; + m_labeledAsReadonly = other.m_labeledAsReadonly; + m_encoding = other.m_encoding; + m_descEncoding = other.m_descEncoding; + if (other.isEmpty()) { + m_ptr.reset(); + } else { + m_ptr = make_unique(m_size); + std::copy(other.m_ptr.get(), other.m_ptr.get() + other.m_size, m_ptr.get()); } return *this; } diff --git a/tagvalue.h b/tagvalue.h index 8fa155e..3240f26 100644 --- a/tagvalue.h +++ b/tagvalue.h @@ -396,7 +396,7 @@ inline void TagValue::clearDataAndMetadata() * \brief Returns the size of the assigned value in bytes. * \remarks Meta data such as description and MIME type is not considered as part of the assigned value. */ -inline size_t TagValue::dataSize() const +inline std::size_t TagValue::dataSize() const { return m_size; } diff --git a/vorbis/vorbiscommentfield.cpp b/vorbis/vorbiscommentfield.cpp index 7857981..21769bb 100644 --- a/vorbis/vorbiscommentfield.cpp +++ b/vorbis/vorbiscommentfield.cpp @@ -191,6 +191,9 @@ bool VorbisCommentField::make(BinaryWriter &writer, VorbisCommentFlags flags, Di pictureBlock.make(bufferStream); valueString = encodeBase64(reinterpret_cast(buffer.get()), requiredSize); + } catch (const Failure &) { + diag.emplace_back(DiagLevel::Critical, "Unable to make METADATA_BLOCK_PICTURE struct from the assigned value.", context); + throw; } catch (...) { catchIoFailure(); diag.emplace_back(DiagLevel::Critical, "An IO error occured when writing the METADATA_BLOCK_PICTURE struct.", context); @@ -200,7 +203,12 @@ bool VorbisCommentField::make(BinaryWriter &writer, VorbisCommentFlags flags, Di // make normal string value valueString = value().toString(); } - writer.writeUInt32LE(id().size() + 1 + valueString.size()); + const auto size(valueString.size() + id().size() + 1); + if (size > numeric_limits::max()) { + diag.emplace_back(DiagLevel::Critical, "Assigned value exceeds the maximum size.", context); + throw InvalidDataException(); + } + writer.writeUInt32LE(static_cast(size)); writer.writeString(id()); writer.writeChar('='); writer.writeString(valueString); diff --git a/wav/waveaudiostream.cpp b/wav/waveaudiostream.cpp index 48cd4b7..181262a 100644 --- a/wav/waveaudiostream.cpp +++ b/wav/waveaudiostream.cpp @@ -114,7 +114,7 @@ void WaveAudioStream::internalParseHeader(Diagnostics &diag) if (m_reader.readUInt32BE() != 0x52494646u) { throw NoDataFoundException(); } - m_istream->seekg(m_startOffset + 8); + m_istream->seekg(static_cast(m_startOffset + 8)); if (m_reader.readUInt32BE() != 0x57415645u) { throw NoDataFoundException(); } @@ -133,7 +133,7 @@ void WaveAudioStream::internalParseHeader(Diagnostics &diag) } break; case 0x64617461u: - m_dataOffset = m_istream->tellg(); + m_dataOffset = static_cast(m_istream->tellg()); m_size = restHeaderLen; m_sampleCount = m_size / m_chunkSize; m_duration = TimeSpan::fromSeconds(static_cast(m_sampleCount) / static_cast(m_samplingFrequency)); @@ -145,7 +145,7 @@ void WaveAudioStream::internalParseHeader(Diagnostics &diag) if (m_format.general != GeneralMediaFormat::Mpeg1Audio || !m_dataOffset) { return; } - m_istream->seekg(m_dataOffset); + m_istream->seekg(static_cast(m_dataOffset)); MpegAudioFrame frame; frame.parseHeader(m_reader); MpegAudioFrameStream::addInfo(frame, *this); @@ -153,7 +153,7 @@ void WaveAudioStream::internalParseHeader(Diagnostics &diag) ? ((static_cast(m_size) * 8.0) / (static_cast(frame.xingFrameCount() * frame.sampleCount()) / static_cast(frame.samplingFrequency())) / 1024.0) : frame.bitrate(); - m_bytesPerSecond = m_bitrate * 125; + m_bytesPerSecond = static_cast(m_bitrate * 125); m_duration = TimeSpan::fromSeconds(static_cast(m_size) / (m_bitrate * 128.0)); }