/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001-2009 Josh Coalson
- * Copyright (C) 2011-2016 Xiph.Org Foundation
+ * Copyright (C) 2011-2022 Xiph.Org Foundation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
do {
if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) {
FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it);
- FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height;
- /* check constraints */
- if(
- (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) &&
- (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) &&
- (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) &&
- obj->data.picture.width <= max_width &&
- obj->data.picture.height <= max_height &&
- obj->data.picture.depth <= max_depth &&
- obj->data.picture.colors <= max_colors &&
- (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen))
- ) {
- if(*picture)
- FLAC__metadata_object_delete(*picture);
- *picture = obj;
- max_area_seen = area;
- max_depth_seen = obj->data.picture.depth;
- }
- else {
- FLAC__metadata_object_delete(obj);
+ if(0 != obj) {
+ FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height;
+
+ /* check constraints */
+ if(
+ (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) &&
+ (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) &&
+ (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) &&
+ obj->data.picture.width <= max_width &&
+ obj->data.picture.height <= max_height &&
+ obj->data.picture.depth <= max_depth &&
+ obj->data.picture.colors <= max_colors &&
+ (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen))
+ ) {
+ if(*picture)
+ FLAC__metadata_object_delete(*picture);
+ *picture = obj;
+ max_area_seen = area;
+ max_depth_seen = obj->data.picture.depth;
+ }
+ else {
+ FLAC__metadata_object_delete(obj);
+ }
}
}
} while(FLAC__metadata_simple_iterator_next(it));
case 0:
iterator->depth = 0;
iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file);
- return read_metadata_block_header_(iterator);
+ ret = read_metadata_block_header_(iterator);
+ /* The first metadata block must be a streaminfo. If this is not the
+ * case, the file is invalid and assumptions made elsewhere in the
+ * code are invalid */
+ if(iterator->type != FLAC__METADATA_TYPE_STREAMINFO) {
+ iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
+ return false;
+ }
+ return ret;
case 1:
iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
return false;
FLAC__ASSERT(0 != iterator);
FLAC__ASSERT(0 != iterator->file);
- return iterator->offset[iterator->depth];
+ return (off_t)iterator->offset[iterator->depth];
}
FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator)
return false;
}
+#if defined(_MSC_VER)
+// silence three MSVC warnings 'conversion from 'conversion from 'const __int64' to 'uint32_t', possible loss of data'
+#pragma warning ( disable : 4244 )
+#endif
+
/* Returns the new length of the chain, or 0 if there was an error. */
/* WATCHOUT: This can get called multiple times before a write, so
* it should still work when this happens.
return current_length;
}
+#if defined(_MSC_VER)
+#pragma warning ( default : 4244 )
+#endif
+
static FLAC__bool chain_read_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Tell tell_cb)
{
FLAC__Metadata_Node *node;
chain->initial_length = chain_calculate_length_(chain);
+ if(chain->initial_length == 0) {
+ /* Ogg FLAC file must have at least streaminfo and vorbis comment */
+ chain->status = FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
+ return false;
+ }
+
return true;
}
LBS_BLOCK_REMOVED
} LastBlockState;
+#if defined(_MSC_VER)
+// silence three MSVC warnings 'conversion from 'conversion from 'const __int64' to 'uint32_t', possible loss of data'
+#pragma warning ( disable : 4244 )
+#endif
+
FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
{
/* This does all the same checks that are in chain_prepare_for_write_()
return (current_length != chain->initial_length);
}
+#if defined(_MSC_VER)
+#pragma warning ( default : 4244 )
+#endif
+
FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats)
{
struct flac_stat_s stats;
if(0 != entry->entry)
free(entry->entry);
- if(entry->length == 0) {
- entry->entry = 0;
- }
- else {
- if(0 == (entry->entry = safe_malloc_add_2op_(entry->length, /*+*/1)))
- return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
+ if(0 == (entry->entry = safe_malloc_add_2op_(entry->length, /*+*/1)))
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
- if(read_cb(entry->entry, 1, entry->length, handle) != entry->length)
- return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+ if(entry->length > 0 && read_cb(entry->entry, 1, entry->length, handle) != entry->length)
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
- entry->entry[entry->length] = '\0';
- }
+ entry->entry[entry->length] = '\0';
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
if(block->num_comments == 0) {
block->comments = 0;
}
+ else if(block->num_comments > (block_length >> 2)) { /* each comment needs at least 4 byte */
+ block->num_comments = 0;
+ status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
+ goto skip;
+ }
else if(0 == (block->comments = calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) {
block->num_comments = 0;
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
*length = unpack_uint32_(buffer, length_len);
+ if(*length > (1u << FLAC__STREAM_METADATA_LENGTH_LEN)) /* data cannot be larger than FLAC metadata block */
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
+
if(0 != *data)
free(*data);
void set_file_stats_(const char *filename, struct flac_stat_s *stats)
{
-#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
+#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) && !defined(_WIN32)
struct timespec srctime[2] = {};
srctime[0].tv_sec = stats->st_atime;
srctime[1].tv_sec = stats->st_mtime;