afh: Fix fd leak.
authorAndre Noll <maan@systemlinux.org>
Sun, 15 Dec 2013 21:39:21 +0000 (22:39 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Thu, 15 Jan 2015 20:57:28 +0000 (21:57 +0100)
The main() function of para_afh obtains the open file descriptor from
mmap_full_file() which is then passed to compute_afhi(). If this file
descriptor is never closed, we have an fd leak.

Unfortunately it depends on the audio format handler whether fd
gets closed or not: the mp3 audio format handler closes it through
libid3tag's id3_file_close() while all other audio format handlers
leave it open.

Fix this by changing mp3_get_id3() to operate on a copy of the fd
instead so that the original fd remains open. The newly added close()
in afh.c thus fixes the fd leak and never closes an invalid fd.

afh.c
mp3_afh.c

diff --git a/afh.c b/afh.c
index 49629cb..f3c25a2 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -111,6 +111,7 @@ int main(int argc, char **argv)
                        printf("\n");
                        clear_afhi(&afhi);
                }
+               close(fd);
                ret2 = para_munmap(audio_file_data, audio_file_size);
                if (ret2 < 0 && ret >= 0)
                        ret = ret2;
index cc3f49f..2506b95 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -126,9 +126,19 @@ static char *get_strings(struct id3_frame *fr)
 static void mp3_get_id3(__a_unused unsigned char *map,
                __a_unused size_t numbytes, int fd, struct taginfo *tags)
 {
-       int i;
+       int i, new_fd;
        struct id3_tag *id3_t;
-       struct id3_file *id3_f = id3_file_fdopen(fd, ID3_FILE_MODE_READONLY);
+       struct id3_file *id3_f;
+
+       /*
+        * We are not supposed to close fd, but to avoid memory leaks we must
+        * call id3_file_close() on the id3_file after we are done. As
+        * id3_file_close() closes fd, we first create a copy for libid3tag.
+        */
+       new_fd = dup(fd);
+       if (new_fd < 0)
+               return;
+       id3_f = id3_file_fdopen(new_fd, ID3_FILE_MODE_READONLY);
 
        if (!id3_f)
                return;