Commit e140a280 authored by Max Kellermann's avatar Max Kellermann

archive/iso9660: check path buffer bounds

parent de61c3b9
...@@ -2,6 +2,8 @@ ver 0.19.14 (not yet released) ...@@ -2,6 +2,8 @@ ver 0.19.14 (not yet released)
* decoder * decoder
- dsdiff: fix off-by-one buffer overflow - dsdiff: fix off-by-one buffer overflow
- opus: limit tag size to 64 kB - opus: limit tag size to 64 kB
* archive
- iso9660: fix buffer overflow
* fix build failures on non-glibc builds due to constexpr Mutex * fix build failures on non-glibc builds due to constexpr Mutex
ver 0.19.13 (2016/02/23) ver 0.19.13 (2016/02/23)
......
...@@ -66,7 +66,10 @@ public: ...@@ -66,7 +66,10 @@ public:
return iso9660_iso_seek_read(iso, ptr, start, i_size); 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); ArchiveVisitor &visitor);
virtual void Close() override { virtual void Close() override {
...@@ -85,7 +88,7 @@ static constexpr Domain iso9660_domain("iso9660"); ...@@ -85,7 +88,7 @@ static constexpr Domain iso9660_domain("iso9660");
/* archive open && listing routine */ /* archive open && listing routine */
inline void inline void
Iso9660ArchiveFile::Visit(char *path, size_t length, Iso9660ArchiveFile::Visit(char *path, size_t length, size_t capacity,
ArchiveVisitor &visitor) ArchiveVisitor &visitor)
{ {
auto *entlist = iso9660_ifs_readdir(iso, path); auto *entlist = iso9660_ifs_readdir(iso, path);
...@@ -102,12 +105,16 @@ Iso9660ArchiveFile::Visit(char *path, size_t length, ...@@ -102,12 +105,16 @@ Iso9660ArchiveFile::Visit(char *path, size_t length,
continue; continue;
size_t filename_length = strlen(filename); 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); memcpy(path + length, filename, filename_length + 1);
size_t new_length = length + filename_length; size_t new_length = length + filename_length;
if (iso9660_stat_s::_STAT_DIR == statbuf->type ) { if (iso9660_stat_s::_STAT_DIR == statbuf->type ) {
memcpy(path + new_length, "/", 2); memcpy(path + new_length, "/", 2);
Visit(path, new_length + 1, visitor); Visit(path, new_length + 1, capacity, visitor);
} else { } else {
//remove leading / //remove leading /
visitor.VisitArchiveEntry(path + 1); visitor.VisitArchiveEntry(path + 1);
...@@ -135,7 +142,7 @@ void ...@@ -135,7 +142,7 @@ void
Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor) Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor)
{ {
char path[4096] = "/"; char path[4096] = "/";
Visit(path, 1, visitor); Visit(path, 1, sizeof(path), visitor);
} }
/* single archive handling */ /* single archive handling */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment