Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ff35aa07dc | ||
![]() |
a3afd5178c | ||
![]() |
f1285a6dfd | ||
![]() |
cf7c1afb93 | ||
![]() |
e140a28073 | ||
![]() |
de61c3b962 | ||
![]() |
c46fc4531b | ||
![]() |
065a9ed10f | ||
![]() |
e44c0254f7 | ||
![]() |
13f9f0315f | ||
![]() |
1532ffe215 | ||
![]() |
b24cbc68ba | ||
![]() |
976fdd76c1 | ||
![]() |
bbda335e02 | ||
![]() |
d2dd6f7c70 | ||
![]() |
e9a544fa98 |
9
NEWS
9
NEWS
@@ -1,3 +1,12 @@
|
|||||||
|
ver 0.19.14 (2016/03/18)
|
||||||
|
* decoder
|
||||||
|
- dsdiff: fix off-by-one buffer overflow
|
||||||
|
- opus: limit tag size to 64 kB
|
||||||
|
* archive
|
||||||
|
- iso9660: fix buffer overflow
|
||||||
|
* fix quadratic runtime bug in the tag pool
|
||||||
|
* fix build failures on non-glibc builds due to constexpr Mutex
|
||||||
|
|
||||||
ver 0.19.13 (2016/02/23)
|
ver 0.19.13 (2016/02/23)
|
||||||
* tags
|
* tags
|
||||||
- aiff, riff: fix ID3 chunk padding
|
- aiff, riff: fix ID3 chunk padding
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
AC_PREREQ(2.60)
|
AC_PREREQ(2.60)
|
||||||
|
|
||||||
AC_INIT(mpd, 0.19.13, musicpd-dev-team@lists.sourceforge.net)
|
AC_INIT(mpd, 0.19.14, musicpd-dev-team@lists.sourceforge.net)
|
||||||
|
|
||||||
VERSION_MAJOR=0
|
VERSION_MAJOR=0
|
||||||
VERSION_MINOR=19
|
VERSION_MINOR=19
|
||||||
VERSION_REVISION=13
|
VERSION_REVISION=14
|
||||||
VERSION_EXTRA=0
|
VERSION_EXTRA=0
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/Main.cxx])
|
AC_CONFIG_SRCDIR([src/Main.cxx])
|
||||||
|
@@ -66,7 +66,11 @@ public:
|
|||||||
return iso9660_iso_seek_read(iso, ptr, start, i_size);
|
return iso9660_iso_seek_read(iso, ptr, start, i_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Visit(const char *path, ArchiveVisitor &visitor);
|
/**
|
||||||
|
* @param capacity the path buffer size
|
||||||
|
*/
|
||||||
|
void Visit(char *path, size_t length, size_t capacity,
|
||||||
|
ArchiveVisitor &visitor);
|
||||||
|
|
||||||
virtual void Close() override {
|
virtual void Close() override {
|
||||||
Unref();
|
Unref();
|
||||||
@@ -84,32 +88,36 @@ static constexpr Domain iso9660_domain("iso9660");
|
|||||||
/* archive open && listing routine */
|
/* archive open && listing routine */
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
Iso9660ArchiveFile::Visit(const char *psz_path, ArchiveVisitor &visitor)
|
Iso9660ArchiveFile::Visit(char *path, size_t length, size_t capacity,
|
||||||
|
ArchiveVisitor &visitor)
|
||||||
{
|
{
|
||||||
CdioList_t *entlist;
|
auto *entlist = iso9660_ifs_readdir(iso, path);
|
||||||
CdioListNode_t *entnode;
|
|
||||||
iso9660_stat_t *statbuf;
|
|
||||||
char pathname[4096];
|
|
||||||
|
|
||||||
entlist = iso9660_ifs_readdir (iso, psz_path);
|
|
||||||
if (!entlist) {
|
if (!entlist) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Iterate over the list of nodes that iso9660_ifs_readdir gives */
|
/* Iterate over the list of nodes that iso9660_ifs_readdir gives */
|
||||||
|
CdioListNode_t *entnode;
|
||||||
_CDIO_LIST_FOREACH (entnode, entlist) {
|
_CDIO_LIST_FOREACH (entnode, entlist) {
|
||||||
statbuf = (iso9660_stat_t *) _cdio_list_node_data (entnode);
|
auto *statbuf = (iso9660_stat_t *)
|
||||||
|
_cdio_list_node_data(entnode);
|
||||||
|
const char *filename = statbuf->filename;
|
||||||
|
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
strcpy(pathname, psz_path);
|
size_t filename_length = strlen(filename);
|
||||||
strcat(pathname, statbuf->filename);
|
if (length + filename_length + 1 >= capacity)
|
||||||
|
/* file name is too long */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memcpy(path + length, filename, filename_length + 1);
|
||||||
|
size_t new_length = length + filename_length;
|
||||||
|
|
||||||
if (iso9660_stat_s::_STAT_DIR == statbuf->type ) {
|
if (iso9660_stat_s::_STAT_DIR == statbuf->type ) {
|
||||||
if (strcmp(statbuf->filename, ".") && strcmp(statbuf->filename, "..")) {
|
memcpy(path + new_length, "/", 2);
|
||||||
strcat(pathname, "/");
|
Visit(path, new_length + 1, capacity, visitor);
|
||||||
Visit(pathname, visitor);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
//remove leading /
|
//remove leading /
|
||||||
visitor.VisitArchiveEntry(pathname + 1);
|
visitor.VisitArchiveEntry(path + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_cdio_list_free (entlist, true);
|
_cdio_list_free (entlist, true);
|
||||||
@@ -133,7 +141,8 @@ iso9660_archive_open(Path pathname, Error &error)
|
|||||||
void
|
void
|
||||||
Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor)
|
Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor)
|
||||||
{
|
{
|
||||||
Visit("/", visitor);
|
char path[4096] = "/";
|
||||||
|
Visit(path, 1, sizeof(path), visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* single archive handling */
|
/* single archive handling */
|
||||||
|
@@ -205,7 +205,7 @@ dsdiff_handle_native_tag(InputStream &is,
|
|||||||
if (length == 0 || length > 60)
|
if (length == 0 || length > 60)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char string[length];
|
char string[length + 1];
|
||||||
char *label;
|
char *label;
|
||||||
label = string;
|
label = string;
|
||||||
|
|
||||||
|
@@ -85,7 +85,7 @@ public:
|
|||||||
|
|
||||||
char *ReadString() {
|
char *ReadString() {
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
if (!ReadWord(length))
|
if (!ReadWord(length) || length >= 65536)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const char *src = (const char *)Read(length);
|
const char *src = (const char *)Read(length);
|
||||||
|
@@ -218,7 +218,7 @@ PulseMixer::SetVolume(unsigned new_volume, Error &error)
|
|||||||
|
|
||||||
struct pa_cvolume cvolume;
|
struct pa_cvolume cvolume;
|
||||||
pa_cvolume_set(&cvolume, volume.channels,
|
pa_cvolume_set(&cvolume, volume.channels,
|
||||||
(pa_volume_t)new_volume * PA_VOLUME_NORM / 100 + 0.5);
|
(new_volume * PA_VOLUME_NORM + 50) / 100);
|
||||||
bool success = pulse_output_set_volume(output, &cvolume, error);
|
bool success = pulse_output_set_volume(output, &cvolume, error);
|
||||||
if (success)
|
if (success)
|
||||||
volume = cvolume;
|
volume = cvolume;
|
||||||
|
@@ -92,7 +92,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unsigned(value) > std::numeric_limits<unsigned>::max()) {
|
if (value > std::numeric_limits<int>::max()) {
|
||||||
command_error(client, ACK_ERROR_ARG,
|
command_error(client, ACK_ERROR_ARG,
|
||||||
"Number too large: %s", s);
|
"Number too large: %s", s);
|
||||||
return false;
|
return false;
|
||||||
@@ -117,7 +117,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unsigned(value) > std::numeric_limits<unsigned>::max()) {
|
if (value > std::numeric_limits<int>::max()) {
|
||||||
command_error(client, ACK_ERROR_ARG,
|
command_error(client, ACK_ERROR_ARG,
|
||||||
"Number too large: %s", s);
|
"Number too large: %s", s);
|
||||||
return false;
|
return false;
|
||||||
|
@@ -23,19 +23,23 @@
|
|||||||
#include "util/Cast.hxx"
|
#include "util/Cast.hxx"
|
||||||
#include "util/VarSize.hxx"
|
#include "util/VarSize.hxx"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
Mutex tag_pool_lock;
|
Mutex tag_pool_lock;
|
||||||
|
|
||||||
static constexpr size_t NUM_SLOTS = 4096;
|
static constexpr size_t NUM_SLOTS = 4093;
|
||||||
|
|
||||||
struct TagPoolSlot {
|
struct TagPoolSlot {
|
||||||
TagPoolSlot *next;
|
TagPoolSlot *next;
|
||||||
unsigned char ref;
|
unsigned char ref;
|
||||||
TagItem item;
|
TagItem item;
|
||||||
|
|
||||||
|
static constexpr unsigned MAX_REF = std::numeric_limits<decltype(ref)>::max();
|
||||||
|
|
||||||
TagPoolSlot(TagPoolSlot *_next, TagType type,
|
TagPoolSlot(TagPoolSlot *_next, TagType type,
|
||||||
const char *value, size_t length)
|
const char *value, size_t length)
|
||||||
:next(_next), ref(1) {
|
:next(_next), ref(1) {
|
||||||
@@ -116,7 +120,7 @@ tag_pool_get_item(TagType type, const char *value, size_t length)
|
|||||||
if (slot->item.type == type &&
|
if (slot->item.type == type &&
|
||||||
length == strlen(slot->item.value) &&
|
length == strlen(slot->item.value) &&
|
||||||
memcmp(value, slot->item.value, length) == 0 &&
|
memcmp(value, slot->item.value, length) == 0 &&
|
||||||
slot->ref < 0xff) {
|
slot->ref < TagPoolSlot::MAX_REF) {
|
||||||
assert(slot->ref > 0);
|
assert(slot->ref > 0);
|
||||||
++slot->ref;
|
++slot->ref;
|
||||||
return &slot->item;
|
return &slot->item;
|
||||||
@@ -135,19 +139,15 @@ tag_pool_dup_item(TagItem *item)
|
|||||||
|
|
||||||
assert(slot->ref > 0);
|
assert(slot->ref > 0);
|
||||||
|
|
||||||
if (slot->ref < 0xff) {
|
if (slot->ref < TagPoolSlot::MAX_REF) {
|
||||||
++slot->ref;
|
++slot->ref;
|
||||||
return item;
|
return item;
|
||||||
} else {
|
} else {
|
||||||
/* the reference counter overflows above 0xff;
|
/* the reference counter overflows above MAX_REF;
|
||||||
duplicate the item, and start with 1 */
|
obtain a reference to a different TagPoolSlot which
|
||||||
|
isn't yet "full" */
|
||||||
size_t length = strlen(item->value);
|
size_t length = strlen(item->value);
|
||||||
auto slot_p = tag_value_slot_p(item->type,
|
return tag_pool_get_item(item->type, item->value, length);
|
||||||
item->value, length);
|
|
||||||
slot = TagPoolSlot::Create(*slot_p, item->type,
|
|
||||||
item->value, strlen(item->value));
|
|
||||||
*slot_p = slot;
|
|
||||||
return &slot->item;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,9 +41,13 @@ class PosixCond {
|
|||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#if defined(__NetBSD__) || defined(__BIONIC__)
|
#ifdef __GLIBC__
|
||||||
/* NetBSD's PTHREAD_COND_INITIALIZER is not compatible with
|
/* optimized constexpr constructor for pthread implementations
|
||||||
"constexpr" */
|
that support it */
|
||||||
|
constexpr PosixCond():cond(PTHREAD_COND_INITIALIZER) {}
|
||||||
|
#else
|
||||||
|
/* slow fallback for pthread implementations that are not
|
||||||
|
compatible with "constexpr" */
|
||||||
PosixCond() {
|
PosixCond() {
|
||||||
pthread_cond_init(&cond, nullptr);
|
pthread_cond_init(&cond, nullptr);
|
||||||
}
|
}
|
||||||
@@ -51,10 +55,6 @@ public:
|
|||||||
~PosixCond() {
|
~PosixCond() {
|
||||||
pthread_cond_destroy(&cond);
|
pthread_cond_destroy(&cond);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* optimized constexpr constructor for sane POSIX
|
|
||||||
implementations */
|
|
||||||
constexpr PosixCond():cond(PTHREAD_COND_INITIALIZER) {}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PosixCond(const PosixCond &other) = delete;
|
PosixCond(const PosixCond &other) = delete;
|
||||||
|
@@ -41,9 +41,13 @@ class PosixMutex {
|
|||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#if defined(__NetBSD__) || defined(__BIONIC__)
|
#ifdef __GLIBC__
|
||||||
/* NetBSD's PTHREAD_MUTEX_INITIALIZER is not compatible with
|
/* optimized constexpr constructor for pthread implementations
|
||||||
"constexpr" */
|
that support it */
|
||||||
|
constexpr PosixMutex():mutex(PTHREAD_MUTEX_INITIALIZER) {}
|
||||||
|
#else
|
||||||
|
/* slow fallback for pthread implementations that are not
|
||||||
|
compatible with "constexpr" */
|
||||||
PosixMutex() {
|
PosixMutex() {
|
||||||
pthread_mutex_init(&mutex, nullptr);
|
pthread_mutex_init(&mutex, nullptr);
|
||||||
}
|
}
|
||||||
@@ -51,10 +55,6 @@ public:
|
|||||||
~PosixMutex() {
|
~PosixMutex() {
|
||||||
pthread_mutex_destroy(&mutex);
|
pthread_mutex_destroy(&mutex);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* optimized constexpr constructor for sane POSIX
|
|
||||||
implementations */
|
|
||||||
constexpr PosixMutex():mutex(PTHREAD_MUTEX_INITIALIZER) {}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PosixMutex(const PosixMutex &other) = delete;
|
PosixMutex(const PosixMutex &other) = delete;
|
||||||
|
@@ -46,7 +46,7 @@ static size_t
|
|||||||
AlignToPageSize(size_t size)
|
AlignToPageSize(size_t size)
|
||||||
{
|
{
|
||||||
static const long page_size = sysconf(_SC_PAGESIZE);
|
static const long page_size = sysconf(_SC_PAGESIZE);
|
||||||
if (page_size > 0)
|
if (page_size == 0)
|
||||||
return size;
|
return size;
|
||||||
|
|
||||||
size_t ps(page_size);
|
size_t ps(page_size);
|
||||||
|
Reference in New Issue
Block a user