tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_extract.py (4221B)


      1 #!/usr/bin/env python
      2 
      3 import os
      4 import tarfile
      5 import tempfile
      6 import zipfile
      7 
      8 import mozfile
      9 import mozunit
     10 import pytest
     11 import stubs
     12 
     13 
     14 @pytest.fixture
     15 def ensure_directory_contents():
     16    """ensure the directory contents match"""
     17 
     18    def inner(directory):
     19        for f in stubs.files:
     20            path = os.path.join(directory, *f)
     21            exists = os.path.exists(path)
     22            if not exists:
     23                print("%s does not exist" % (os.path.join(f)))
     24            assert exists
     25            if exists:
     26                contents = open(path).read().strip()
     27                assert contents == f[-1]
     28 
     29    return inner
     30 
     31 
     32 @pytest.fixture(scope="module")
     33 def tarpath(tmpdir_factory):
     34    """create a stub tarball for testing"""
     35    tmpdir = tmpdir_factory.mktemp("test_extract")
     36 
     37    tempdir = tmpdir.join("stubs").strpath
     38    stubs.create_stub(tempdir)
     39    filename = tmpdir.join("bundle.tar").strpath
     40    archive = tarfile.TarFile(filename, mode="w")
     41    for path in stubs.files:
     42        archive.add(os.path.join(tempdir, *path), arcname=os.path.join(*path))
     43    archive.close()
     44 
     45    assert os.path.exists(filename)
     46    return filename
     47 
     48 
     49 @pytest.fixture(scope="module")
     50 def zippath(tmpdir_factory):
     51    """create a stub zipfile for testing"""
     52    tmpdir = tmpdir_factory.mktemp("test_extract")
     53 
     54    tempdir = tmpdir.join("stubs").strpath
     55    stubs.create_stub(tempdir)
     56    filename = tmpdir.join("bundle.zip").strpath
     57    archive = zipfile.ZipFile(filename, mode="w")
     58    for path in stubs.files:
     59        archive.write(os.path.join(tempdir, *path), arcname=os.path.join(*path))
     60    archive.close()
     61 
     62    assert os.path.exists(filename)
     63    return filename
     64 
     65 
     66 @pytest.fixture(scope="module", params=["tar", "zip"])
     67 def bundlepath(request, tarpath, zippath):
     68    if request.param == "tar":
     69        return tarpath
     70    else:
     71        return zippath
     72 
     73 
     74 def test_extract(tmpdir, bundlepath, ensure_directory_contents):
     75    """test extracting a zipfile"""
     76    dest = tmpdir.mkdir("dest").strpath
     77    mozfile.extract(bundlepath, dest)
     78    ensure_directory_contents(dest)
     79 
     80 
     81 def test_extract_zipfile_missing_file_attributes(tmpdir):
     82    """if files do not have attributes set the default permissions have to be inherited."""
     83    _zipfile = os.path.join(
     84        os.path.dirname(__file__), "files", "missing_file_attributes.zip"
     85    )
     86    assert os.path.exists(_zipfile)
     87    dest = tmpdir.mkdir("dest").strpath
     88 
     89    # Get the default file permissions for the user
     90    fname = os.path.join(dest, "foo")
     91    with open(fname, "w"):
     92        pass
     93    default_stmode = os.stat(fname).st_mode
     94 
     95    files = mozfile.extract_zip(_zipfile, dest)
     96    for filename in files:
     97        assert os.stat(os.path.join(dest, filename)).st_mode == default_stmode
     98 
     99 
    100 def test_extract_non_archive(tarpath, zippath):
    101    """test the generalized extract function"""
    102    # test extracting some non-archive; this should fail
    103    fd, filename = tempfile.mkstemp()
    104    os.write(fd, b"This is not a zipfile or tarball")
    105    os.close(fd)
    106    exception = None
    107 
    108    try:
    109        dest = tempfile.mkdtemp()
    110        mozfile.extract(filename, dest)
    111    except Exception as exc:
    112        exception = exc
    113    finally:
    114        os.remove(filename)
    115        os.rmdir(dest)
    116 
    117    assert isinstance(exception, Exception)
    118 
    119 
    120 def test_extract_ignore(tmpdir, bundlepath):
    121    dest = tmpdir.mkdir("dest").strpath
    122    ignore = ("foo", "**/fleem.txt", "read*.txt")
    123    mozfile.extract(bundlepath, dest, ignore=ignore)
    124 
    125    assert sorted(os.listdir(dest)) == ["bar.txt", "foo.txt"]
    126 
    127 
    128 def test_tarball_escape(tmpdir):
    129    """Ensures that extracting a tarball can't write outside of the intended
    130    destination directory.
    131    """
    132    workdir = tmpdir.mkdir("workdir")
    133    os.chdir(workdir)
    134 
    135    # Generate a "malicious" bundle.
    136    with open("bad.txt", "w") as fh:
    137        fh.write("pwned!")
    138 
    139    def change_name(tarinfo):
    140        tarinfo.name = "../" + tarinfo.name
    141        return tarinfo
    142 
    143    with tarfile.open("evil.tar", "w:xz") as tar:
    144        tar.add("bad.txt", filter=change_name)
    145 
    146    with pytest.raises(RuntimeError):
    147        mozfile.extract_tarball("evil.tar", workdir)
    148    assert not os.path.exists(tmpdir.join("bad.txt"))
    149 
    150 
    151 if __name__ == "__main__":
    152    mozunit.main()