diff --git a/NEWS b/NEWS index 1d6762a54..62ea0c08e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ ver 0.19.14 (not yet released) * decoder - dsdiff: fix off-by-one buffer overflow - opus: limit tag size to 64 kB +* archive + - iso9660: fix buffer overflow * fix build failures on non-glibc builds due to constexpr Mutex ver 0.19.13 (2016/02/23) diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx index 24609f1ed..6b5f47e86 100644 --- a/src/archive/plugins/Iso9660ArchivePlugin.cxx +++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx @@ -66,7 +66,10 @@ public: return iso9660_iso_seek_read(iso, ptr, start, i_size); } - void Visit(char *path, size_t length, + /** + * @param capacity the path buffer size + */ + void Visit(char *path, size_t length, size_t capacity, ArchiveVisitor &visitor); virtual void Close() override { @@ -85,7 +88,7 @@ static constexpr Domain iso9660_domain("iso9660"); /* archive open && listing routine */ inline void -Iso9660ArchiveFile::Visit(char *path, size_t length, +Iso9660ArchiveFile::Visit(char *path, size_t length, size_t capacity, ArchiveVisitor &visitor) { auto *entlist = iso9660_ifs_readdir(iso, path); @@ -102,12 +105,16 @@ Iso9660ArchiveFile::Visit(char *path, size_t length, continue; size_t filename_length = strlen(filename); + if (length + filename_length + 1 >= capacity) + /* file name is too long */ + continue; + memcpy(path + length, filename, filename_length + 1); size_t new_length = length + filename_length; if (iso9660_stat_s::_STAT_DIR == statbuf->type ) { memcpy(path + new_length, "/", 2); - Visit(path, new_length + 1, visitor); + Visit(path, new_length + 1, capacity, visitor); } else { //remove leading / visitor.VisitArchiveEntry(path + 1); @@ -135,7 +142,7 @@ void Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor) { char path[4096] = "/"; - Visit(path, 1, visitor); + Visit(path, 1, sizeof(path), visitor); } /* single archive handling */