miurahr / py7zr

7zip in python3 with ZStandard, PPMd, LZMA2, LZMA1, Delta, BCJ, BZip2, and Deflate compressions, and AES encryption.
https://pypi.org/project/py7zr/
GNU Lesser General Public License v2.1
462 stars 74 forks source link

AttributeError when adding empty string with writestr() #549

Closed kokumura closed 7 months ago

kokumura commented 1 year ago

Describe the bug

SevenZipFile.writestr() raises AttributeError: 'NoneType' object has no attribute 'files' under the following conditions:

  1. The data argument value is an empty string
  2. It is the first write** mthod call for the archive file

Related issue

https://github.com/miurahr/py7zr/issues/398

To Reproduce

Here is a minimal code to reproduce the issue.

import py7zr

with py7zr.SevenZipFile(
    file="test.7z",
    mode="w",
) as archive:

    archive.writestr(
        data="",
        arcname="empty.txt",
    )

Run the code above, the following error occurs.

Traceback (most recent call last):
  File "test-py7zr.py", line 8, in <module>
    archive.writestr(
  File "/path-to-site-packages/py7zr/py7zr.py", line 1093, in writestr
    return self._writestr(data, arcname)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/path-to-site-packages/py7zr/py7zr.py", line 1099, in _writestr
    self._writef(io.BytesIO(data.encode("UTF-8")), arcname)
  File "/path-to-site-packages/py7zr/py7zr.py", line 1086, in _writef
    self.header.files_info.files.append(file_info)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'files'

Expected behavior An empty file is created in the archive file with no errors.

Environment (please complete the following information):

Test data(please attach in the report):

See thre reproduction code above.

Additional context

I found that SevenZipFile._writef() does not call self.header.initialize() when size == 0 (self.header.files_info is None until self.header.initialize() is called.)

https://github.com/miurahr/py7zr/blob/30e4184904cefd48e61c374846239b799134c41b/py7zr/py7zr.py#L1067-L1078

For a workaround, explicitly calling header.initialize() before writestr() solved my problem. (Update) I noticed this workaround is not right. Do not try this. As reported in #398, writing empty file with writestr() seems not working at all.

kokumura commented 1 year ago

I found that #398 covers this problem in more detail. Please close this issue as duplication, sorry.

miurahr commented 1 year ago

@kokumura when you have more time to investigate, it is a chance to dig and fix the long pending problem, flaged help wanted, and join to contributors list with Pull-Reuqest. As always it is welcome.