From 86fdff38d980c39062764a31f40a2ee2c5854d33 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Wed, 27 May 2009 19:16:54 +0200 Subject: [PATCH] Truncate overlong tag info and replace newlines by spaces. The tag info which is computed by the audio format handlers and stored in the audio file table is read into a fixed-size buffer by the audio file selector in open_and_update_audio_file(), passed to the server process and then sent to the client via the stat command. It is not interpreted at all during this process. In particular, it is not essential for correctly streaming the audio file. Vorbis comments and id3v2 tags have no size limit and may contain arbitrary data which may lead to the following twi problems: - As noted by Gerrit Renker, if the tag info is too long to fit into the fixed-size buffer, the current code skips the audio file and removes it from the list of currently admissible files. So para_server fails to stream such files. - If the tag info contains newlines, these are included verbatim in the status output which may confuse para_audiod. This patch truncates the tag info string if it does not fit into the 4K buffer and replaces newlines by spaces. This is a bit ugly but avoids both of the above problems. It's still possible to retrieve the complete tag info via the "ls -lv" command. --- aft.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/aft.c b/aft.c index 3283dda8..995c7552 100644 --- a/aft.c +++ b/aft.c @@ -980,12 +980,66 @@ void make_empty_status_items(char *buf) ); } +static void fixup_taginfo(char *begin, char *end) +{ + char *p = begin; + + for (;;) { + p = strchr(p, '\n'); + if (!p) + break; + if (p >= end - 1) + break; + *p = ' '; + p++; + } +} + +/* crap, remove this ASAP. */ +static int fixup_info_string(char *info_string) +{ + char *t1, *t2, *end; + + if (strncmp(info_string, "audio_file_info:", 16)) + return -ERRNO_TO_PARA_ERROR(EINVAL); + t1 = strstr(info_string, "\ntaginfo1:"); + if (!t1) + return -ERRNO_TO_PARA_ERROR(EINVAL); + t2 = strstr(info_string, "\ntaginfo2: "); + if (!t2) + return -ERRNO_TO_PARA_ERROR(EINVAL); + + end = t2 + strlen(t2) + 1; + fixup_taginfo(info_string + 16, t1); + fixup_taginfo(t1 + 10, t2); + fixup_taginfo(t2 + 10, end); + + if (t1 - info_string < 80 && t2 - t1 < 80 && end - t2 < 80) + return 0; + if (t1 - info_string >= 80) { + memmove(info_string + 80, t1, end - t1); + t1 = info_string + 80; + t2 -= t1 - info_string - 80; + end -= t1 - info_string - 80; + } + if (t2 - t1 >= 80) { + memmove(t1 + 80, t2, end - t2); + end -= t2 - t1 - 80; + t2 = t1 + 80; + } + if (end - t2 >= 80) { + t2[78] = '\n'; + t2[79] = '\0'; + } + return 1; +} + static int make_status_items(struct audio_file_data *afd, struct afs_info *afsi, char *path, long score, HASH_TYPE *hash) { struct ls_data d = { - .afhi = afd->afhi, /* struct copy */ + .afhi = afd->afhi, .afsi = *afsi, .path = path, .score = score, @@ -999,6 +1053,12 @@ static int make_status_items(struct audio_file_data *afd, time_t current_time; int ret; + ret = fixup_info_string(afd->afhi.info_string); + if (ret < 0) { + PARA_WARNING_LOG("ignoring invalid tag info\n"); + afd->afhi.info_string[0] = '\0'; + } else if (ret) + PARA_NOTICE_LOG("truncated overlong tag info\n"); time(¤t_time); ret = print_list_item(&d, &opts, &pb, current_time); /* frees info string */ afd->afhi.info_string = NULL; -- 2.39.2