diff options
author | Eric Wong <normalperson@yhbt.net> | 2008-09-03 02:14:52 -0700 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2008-09-03 03:11:36 -0700 |
commit | cdc9bb460e9536577d2747d51c76306a91b3d064 (patch) | |
tree | 08fd64464118041c8be657fae1e8c49310604104 | |
parent | 29fd1316fc0e098451d54fb4ee8ba84a422701f6 (diff) | |
download | mpd-cdc9bb460e9536577d2747d51c76306a91b3d064.tar.gz mpd-cdc9bb460e9536577d2747d51c76306a91b3d064.tar.xz mpd-cdc9bb460e9536577d2747d51c76306a91b3d064.zip |
tag: fix segfault on update
clearMpdTag could be called on a tag that was still in a
tag_begin_add transaction before tag_end_add is called. This
was causing free() to attempt to operate on bulk.items; which is
un-free()-able. Now instead we unmark the bulk.busy to avoid
committing the tags to the heap only to be immediately freed.
Additionally, we need to remember to call tag_end_add() when
a song is updated before we NULL song->tag to avoid tripping
an assertion the next time tag_begin_add() is called.
-rw-r--r-- | src/song.c | 1 | ||||
-rw-r--r-- | src/tag.c | 35 |
2 files changed, 22 insertions, 14 deletions
diff --git a/src/song.c b/src/song.c index 063b0a7b6..9b8b7d4db 100644 --- a/src/song.c +++ b/src/song.c @@ -201,6 +201,7 @@ static void insertSongIntoList(SongList * list, ListNode ** nextSongNode, Song *tempSong = (Song *) ((*nextSongNode)->data); if (tempSong->mtime != song->mtime) { tag_free(tempSong->tag); + tag_end_add(song->tag); tempSong->tag = song->tag; tempSong->mtime = song->mtime; song->tag = NULL; @@ -26,6 +26,19 @@ #include "tagTracker.h" #include "song.h" +/** + * Maximum number of items managed in the bulk list; if it is + * exceeded, we switch back to "normal" reallocation. + */ +#define BULK_MAX 64 + +static struct { +#ifndef NDEBUG + int busy; +#endif + struct tag_item *items[BULK_MAX]; +} bulk; + const char *mpdTagItemKeys[TAG_NUM_OF_ITEM_TYPES] = { "Artist", "Album", @@ -288,8 +301,15 @@ static void clearMpdTag(struct mpd_tag *tag) tag_pool_put_item(tag->items[i]); } - if (tag->items) + if (tag->items == bulk.items) { +#ifndef NDEBUG + assert(bulk.busy); + bulk.busy = 0; +#endif + } else if (tag->items) { free(tag->items); + } + tag->items = NULL; tag->numOfItems = 0; @@ -363,19 +383,6 @@ static inline const char *fix_utf8(const char *str, size_t *length_r) { return temp; } -/** - * Maximum number of items managed in the bulk list; if it is - * exceeded, we switch back to "normal" reallocation. - */ -#define BULK_MAX 64 - -static struct { -#ifndef NDEBUG - int busy; -#endif - struct tag_item *items[BULK_MAX]; -} bulk; - void tag_begin_add(struct mpd_tag *tag) { assert(!bulk.busy); |