# HG changeset patch # Parent 376c2d81d0e2e8ec424d4aafabfbd75e42ea3804 Allow AF_UNIX pathnames up to the maximum 108 bytes on Linux, since it does not require sun_path to be null terminated. diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1581,6 +1581,44 @@ class TestExceptions(unittest.TestCase): self.assertTrue(issubclass(socket.gaierror, socket.error)) self.assertTrue(issubclass(socket.timeout, socket.error)) +@unittest.skipUnless(sys.platform.startswith('linux'), 'Linux specific test') +class TestLinuxPathLen(unittest.TestCase): + + # Test AF_UNIX path length limits on Linux. + + UNIX_PATH_MAX = 108 + + def setUp(self): + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.to_unlink = [] + + def tearDown(self): + self.sock.close() + for name in self.to_unlink: + test_support.unlink(name) + + def pathname(self, length): + # Return a pathname of the given length. + path = os.path.abspath(test_support.TESTFN) + return path + "a" * (length - len(path)) + + def testPathTooLong(self): + # Check we can't bind to a path longer than the assumed maximum. + path = self.pathname(self.UNIX_PATH_MAX + 1) + with self.assertRaisesRegexp(socket.error, "AF_UNIX path too long"): + self.sock.bind(path) + self.to_unlink.append(path) + + def testMaxPathLen(self): + # Test binding to a path of the maximum length and reading the + # address back. In this case, sun_path is not null terminated, + # and makesockaddr() used to read past the end of it. + path = self.pathname(self.UNIX_PATH_MAX) + self.sock.bind(path) + self.to_unlink.append(path) + self.assertEqual(self.sock.getsockname(), path) + os.stat(path) + @unittest.skipUnless(sys.platform == 'linux', 'Linux specific test') class TestLinuxAbstractNamespace(unittest.TestCase): @@ -1793,6 +1831,7 @@ def test_main(): NetworkConnectionBehaviourTest, ]) tests.append(BasicSocketPairTest) + tests.append(TestLinuxPathLen) tests.append(TestLinuxAbstractNamespace) tests.extend([TIPCTest, TIPCThreadableTest]) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1251,27 +1251,16 @@ getsockaddrarg(PySocketSockObject *s, Py addr = (struct sockaddr_un*)addr_ret; #ifdef linux - if (len > 0 && path[0] == 0) { - /* Linux abstract namespace extension */ - if (len > sizeof addr->sun_path) { - PyErr_SetString(socket_error, - "AF_UNIX path too long"); - return 0; - } - } - else -#endif /* linux */ - { - /* regular NULL-terminated string */ - if (len >= sizeof addr->sun_path) { - PyErr_SetString(socket_error, - "AF_UNIX path too long"); - return 0; - } - addr->sun_path[len] = 0; + if (len > sizeof(addr->sun_path)) { +#else + if (len >= sizeof(addr->sun_path)) { +#endif + PyErr_SetString(socket_error, "AF_UNIX path too long"); + return 0; } addr->sun_family = s->sock_family; memcpy(addr->sun_path, path, len); + memset(addr->sun_path + len, 0, sizeof(addr->sun_path) - len); #if defined(PYOS_OS2) *len_ret = sizeof(*addr); #else