Package: tagpy
Version: 0.91-1
Severity: normal
Tags: patch
Subject: tagpy: Fix segfault in tapgy.id3v2.Tag.addFrame()
Package: tagpy
Version: 0.91-1
Severity: important
Tags: patch
Adding a new Frame to an ID3v2 Tag reproducibly causes a segementation
fault. The TagLib documentation specifies that Tag::addFrame() takes
ownership of the pointer passed to it, but tagpy ignores this. I think
the result is that both, python and TagLib try to free() the Frame
pointer.
The crash is reproducible using the following python script:
import tagpy
import tagpy.id3v2
fileref = tagpy.FileRef('file.mp3')
file = fileref.file()
tag = file.ID3v2Tag(True)
frame = tagpy.id3v2.UniqueFileIdentifierFrame('blah', 'blah')
tag.addFrame(frame)
file.save()
According to the Boost.Python FAQ[1] the solution would be to use
std::auto_ptr. But I wasn't able to get it to work, so I worked around
using std::auto_ptr by simply cloning the Frame object before passing it
to addFrame().
Maybe somebody who is more knowledgeable in C++ than I am, can fix this
the right way.
[1] http://www.boost.org/libs/python/doc/v2/faq.html#ownership
-- System Information:
Debian Release: lenny/sid
APT prefers unstable
APT policy: (500, 'unstable'), (500, 'testing'), (1, 'experimental')
Architecture: i386 (i686)
Kernel: Linux 2.6.22.2 (SMP w/2 CPU cores; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
-- System Information:
Debian Release: lenny/sid
APT prefers unstable
APT policy: (500, 'unstable'), (500, 'testing'), (1, 'experimental')
Architecture: i386 (i686)
Kernel: Linux 2.6.22.2 (SMP w/2 CPU cores; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
--- orig/tagpy-0.91/src/id3.cpp 2006-03-21 19:08:11.000000000 +0100
+++ modified/tagpy-0.91/src/id3.cpp 2007-08-04 15:33:36.393646285 +0200
@@ -35,6 +35,12 @@
void id3v2_Tag_removeFrame(ID3v2::Tag &t, ID3v2::Frame *f) {
t.removeFrame(f); }
+ void id3v2_Tag_addFrame(ID3v2::Tag &t, ID3v2::Frame *f)
+ {
+ ID3v2::Frame *f_clone =
ID3v2::FrameFactory::instance()->createFrame(f->render());
+ t.addFrame(f_clone);
+ }
+
object id3v2_rvf_channels(const ID3v2::RelativeVolumeFrame &rvf)
{
List<ID3v2::RelativeVolumeFrame::ChannelType> l = rvf.channels();
@@ -171,7 +177,7 @@
.def("frameList", fl1, return_internal_reference<>())
.def("frameList", fl2, return_internal_reference<>())
- .DEF_SIMPLE_METHOD(addFrame)
+ .def("addFrame", &id3v2_Tag_addFrame)
.DEF_SIMPLE_METHOD(removeFrame)
.DEF_SIMPLE_METHOD(removeFrames)