File size: 5,112 Bytes
859a779 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 Canonical Ltd
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.
"""Unit tests for verifying the correctness of DebFile descriptor handling."""
import os
import unittest
from test_all import get_library_dir
import sys
libdir = get_library_dir()
if libdir:
sys.path.insert(0, libdir)
import apt_inst
import gc
import subprocess
import tempfile
import warnings
@unittest.skipIf(
not os.path.exists("/proc/self/fd"), "no /proc/self/fd available"
)
class TestCVE_2020_27351(unittest.TestCase):
""" test the debfile """
GOOD_DEB = "data/test_debs/utf8-package_1.0-1_all.deb"
def test_success(self):
"""opening package successfully should not leak fd"""
before = os.listdir("/proc/self/fd")
apt_inst.DebFile(self.GOOD_DEB)
after = os.listdir("/proc/self/fd")
self.assertEqual(before, after)
def test_regression_bug_977000(self):
"""opening with a file handle should work correctly"""
with open(self.GOOD_DEB) as good_deb:
apt_inst.DebFile(good_deb).control.extractdata("control")
def test_regression_bug_977000_2(self):
"""file object <-> debfile cycles should be collected by gc."""
class Cycle(object):
def __init__(self, fname):
self.file = open(fname)
self.deb = apt_inst.DebFile(self)
def fileno(self):
return self.file.fileno()
before = os.listdir("/proc/self/fd")
Cycle(self.GOOD_DEB).deb.control.extractdata("control")
warnings.filterwarnings("ignore", category=ResourceWarning)
gc.collect()
warnings.resetwarnings()
after = os.listdir("/proc/self/fd")
self.assertEqual(before, after)
def test_regression_bug_977000_2_ar(self):
"""file object <-> debfile cycles should be collected by gc."""
class Cycle(object):
def __init__(self, fname):
self.file = open(fname)
self.deb = apt_inst.ArArchive(self)
def fileno(self):
return self.file.fileno()
before = os.listdir("/proc/self/fd")
Cycle(self.GOOD_DEB).deb.gettar("control.tar.gz", "gzip").extractdata(
"control"
)
warnings.filterwarnings("ignore", category=ResourceWarning)
gc.collect()
warnings.resetwarnings()
after = os.listdir("/proc/self/fd")
self.assertEqual(before, after)
def test_success_a_member(self):
"""fd should be kept around as long as a tarfile member"""
before = os.listdir("/proc/self/fd")
data = apt_inst.DebFile(self.GOOD_DEB).data
after = os.listdir("/proc/self/fd")
self.assertEqual(len(before), len(after) - 1)
del data
after = os.listdir("/proc/self/fd")
self.assertEqual(before, after)
def _create_deb_without(self, member):
temp = tempfile.NamedTemporaryFile(mode="wb")
try:
with open(self.GOOD_DEB, "rb") as deb:
temp.write(deb.read())
temp.flush()
subprocess.check_call(["ar", "d", temp.name, member])
return temp
except Exception as e:
temp.close()
raise e
def test_nocontrol(self):
"""opening package without control.tar.gz should not leak fd"""
before = os.listdir("/proc/self/fd")
with self._create_deb_without("control.tar.gz") as temp:
try:
apt_inst.DebFile(temp.name)
except SystemError as e:
self.assertIn("control.tar", str(e))
else:
self.fail("Did not raise an exception")
after = os.listdir("/proc/self/fd")
self.assertEqual(before, after)
def test_nodata(self):
"""opening package without data.tar.gz should not leak fd"""
before = os.listdir("/proc/self/fd")
with self._create_deb_without("data.tar.gz") as temp:
try:
apt_inst.DebFile(temp.name)
except SystemError as e:
self.assertIn("data.tar", str(e))
else:
self.fail("Did not raise an exception")
after = os.listdir("/proc/self/fd")
self.assertEqual(before, after)
def test_no_debian_binary(self):
"""opening package without debian-binary should not leak fd"""
before = os.listdir("/proc/self/fd")
with self._create_deb_without("debian-binary") as temp:
try:
apt_inst.DebFile(temp.name)
except SystemError as e:
self.assertIn("missing debian-binary", str(e))
else:
self.fail("Did not raise an exception")
after = os.listdir("/proc/self/fd")
self.assertEqual(before, after)
if __name__ == "__main__":
# logging.basicConfig(level=logging.DEBUG)
unittest.main()
|