com_add(): Allow paths and afhi to exceed 64K.
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 6 Sep 2015 13:05:30 +0000 (15:05 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Tue, 8 Sep 2015 07:41:04 +0000 (09:41 +0200)
The add command has the unnecessary limitation that for each audio
file to be added, the length of the path plus the size of serialized
audio format handler info structure (afhi) must not exceed 64K.

An afhi bigger than that is quite possible, given that it contains
the meta information of the file, for example an ID3v2 tag which can
contain almost unlimited amounts of data. If the 64K limit is exceeded,
all kinds of bad things may happen. So this issue definitely needs
to be addressed.

Specifically, save_add_callback_buffer() must be fixed. In this
function we serialize the data to be passed from the add command
handler to its callback. This includes path, afhi and the chunk table,
which are all variable in size. To cope with variable sizes, the
start of the buffer contains fields in which the offsets are stored
at which afhi and chunk table are located, relative to the start of
the serialized buffer. The problem is that the offset fields are only
16 bit wide, allowing for a maximal size of 64K.

This commit makes the offsets 32 bit wide and reorders them a
bit. Also, the CAB_AUDIO_FORMAT_OFFSET identifier is renamed to
CAB_AUDIO_FORMAT_ID_OFFSET.

aft.c

diff --git a/aft.c b/aft.c
index c4558f2..bf86acf 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1563,16 +1563,16 @@ static struct osl_row *find_hash_sister(unsigned char *hash)
 
 /** The format of the data stored by save_audio_file_data(). */
 enum com_add_buffer_offsets {
-       /** afhi (if present) starts here. */
+       /* afhi (if present) starts at this offset. */
        CAB_AFHI_OFFSET_POS = 0,
        /** Start of the chunk table (if present). */
-       CAB_CHUNKS_OFFSET_POS = 2,
-       /** Audio format id. */
-       CAB_AUDIO_FORMAT_OFFSET = 4,
+       CAB_CHUNKS_OFFSET_POS = 4,
        /** Flags given to the add command. */
-       CAB_FLAGS_OFFSET = 5,
+       CAB_FLAGS_OFFSET = 8,
+       /** Audio format id. */
+       CAB_AUDIO_FORMAT_ID_OFFSET = 12,
        /** The hash of the audio file being added. */
-       CAB_HASH_OFFSET = 9,
+       CAB_HASH_OFFSET = 13,
        /** Start of the path of the audio file. */
        CAB_PATH_OFFSET = (CAB_HASH_OFFSET + HASH_SIZE),
 };
@@ -1593,27 +1593,23 @@ static void save_add_callback_buffer(unsigned char *hash, const char *path,
        size_t size = CAB_PATH_OFFSET + path_len + afhi_size
                + sizeof_chunk_table(afhi);
        char *buf = para_malloc(size);
-       uint16_t pos;
-
-       write_u8(buf + CAB_AUDIO_FORMAT_OFFSET, audio_format_num);
-       write_u32(buf + CAB_FLAGS_OFFSET, flags);
-
-       memcpy(buf + CAB_HASH_OFFSET, hash, HASH_SIZE);
-       strcpy(buf + CAB_PATH_OFFSET, path);
+       uint32_t pos;
 
        pos = CAB_PATH_OFFSET + path_len;
-       PARA_DEBUG_LOG("size: %zu, afhi starts at %d\n", size, pos);
-       PARA_DEBUG_LOG("last afhi byte: %p, pos %zu\n", buf + pos + afhi_size - 1,
-               pos + afhi_size - 1);
-       write_u16(buf + CAB_AFHI_OFFSET_POS, pos);
+       write_u32(buf + CAB_AFHI_OFFSET_POS, pos);
        save_afhi(afhi, buf + pos);
-
        pos += afhi_size;
-       PARA_DEBUG_LOG("size: %zu, chunks start at %d\n", size, pos);
-       write_u16(buf + CAB_CHUNKS_OFFSET_POS, pos);
+
+       write_u32(buf + CAB_CHUNKS_OFFSET_POS, pos);
        if (afhi)
                save_chunk_table(afhi, buf + pos);
-       PARA_DEBUG_LOG("last byte in buf: %p\n", buf + size - 1);
+
+       write_u32(buf + CAB_FLAGS_OFFSET, flags);
+       write_u8(buf + CAB_AUDIO_FORMAT_ID_OFFSET, audio_format_num);
+
+       memcpy(buf + CAB_HASH_OFFSET, hash, HASH_SIZE);
+       strcpy(buf + CAB_PATH_OFFSET, path);
+
        obj->data = buf;
        obj->size = size;
 }
@@ -1757,8 +1753,8 @@ static void com_add_callback(int fd, const struct osl_object *query)
                        goto out;
        }
        /* no hs or force mode, child must have sent afhi */
-       afhi_offset = read_u16(buf + CAB_AFHI_OFFSET_POS);
-       chunks_offset = read_u16(buf + CAB_CHUNKS_OFFSET_POS);
+       afhi_offset = read_u32(buf + CAB_AFHI_OFFSET_POS);
+       chunks_offset = read_u32(buf + CAB_CHUNKS_OFFSET_POS);
 
        objs[AFTCOL_AFHI].data = buf + afhi_offset;
        objs[AFTCOL_AFHI].size = chunks_offset - afhi_offset;
@@ -1811,7 +1807,7 @@ static void com_add_callback(int fd, const struct osl_object *query)
                        goto out;
        }
        default_afsi.last_played = time(NULL) - 365 * 24 * 60 * 60;
-       default_afsi.audio_format_id = read_u8(buf + CAB_AUDIO_FORMAT_OFFSET);
+       default_afsi.audio_format_id = read_u8(buf + CAB_AUDIO_FORMAT_ID_OFFSET);
 
        objs[AFTCOL_AFSI].data = &afsi_buf;
        objs[AFTCOL_AFSI].size = AFSI_SIZE;