archive/iso9660: check path buffer bounds
This commit is contained in:
		
							
								
								
									
										2
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								NEWS
									
									
									
									
									
								
							| @@ -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: | |||||||
| 		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 */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann