Quick overview
QuaZip::close() may not be safely called twice (once explicitly, a second time by the d'tor) in some cases where there is a file I/O error, because some internal pointers will be invalidated after the first close() call and close will not set itself back to the mdNotOpen mode.
More in-depth
I recently received a crash report that's been easy to reproduce in my project, but difficult to reproduce outside of it.
I am using QuaZip 0.8.3, but the master branch appears to be the same. Windows platform (7 and 10), MSVC 2019, Qt 5.15.3. x64 architecture
The original field report is that if we are writing a zip file to a flash drive, and the flash drive is removed during the process, QuaZip will cause a crash with a dangling pointer.
I've stepped into the code, and while I don't have a full grasp on the internals, I believe the following is happening:
QuaZip is instantiated on the stack with a path to a flash drive
The file is opened with mdCreate
We write some contents to the file before it is pulled, instantiating QuaZipFile objects and doing the file I/O there
User pulls the flash drive
We continue to write contents, which fail in some way (very expected!)
We explicitly call QuaZip::close()
6b. QuaZip close() will have p->zipError set to -1 / 0xFFFFFFFF
6c. Because we opened with a file name, p->ioDevice will be deleted
6d. Because we have a zipError, we do NOT set p->mode back to mdNotOpen
QuaZip falls out of scope
7b. QuaZip still believes it is open, and attempts to close the file again
7c. Some internal file handles are now dangling, and will be accessed
7d. Specifically, we crash in qiodevice64_tell_file_func when iodevice->isSequential() is called.
7e. Callstack is:
I have been unable to reproduce in a separate app using much of the same code, so there may be something about my environment that is off.
Generically, I do believe that close() should be always setting p->mode to mdNotOpen. Even if it fails, we should not attempt to reference freed resources again later.
Quick overview QuaZip::close() may not be safely called twice (once explicitly, a second time by the d'tor) in some cases where there is a file I/O error, because some internal pointers will be invalidated after the first close() call and close will not set itself back to the mdNotOpen mode.
More in-depth I recently received a crash report that's been easy to reproduce in my project, but difficult to reproduce outside of it.
I am using QuaZip 0.8.3, but the master branch appears to be the same. Windows platform (7 and 10), MSVC 2019, Qt 5.15.3. x64 architecture
The original field report is that if we are writing a zip file to a flash drive, and the flash drive is removed during the process, QuaZip will cause a crash with a dangling pointer.
I've stepped into the code, and while I don't have a full grasp on the internals, I believe the following is happening:
I have been unable to reproduce in a separate app using much of the same code, so there may be something about my environment that is off.
Generically, I do believe that close() should be always setting p->mode to mdNotOpen. Even if it fails, we should not attempt to reference freed resources again later.