archive/iso9660: check path buffer bounds

This commit is contained in:
Max Kellermann 2016-03-07 14:18:39 +01:00
parent de61c3b962
commit e140a28073
2 changed files with 13 additions and 4 deletions

2
NEWS
View File

@ -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)

View File

@ -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");
/* 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,
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
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 */