Skip to content

Commit 072f50f

Browse files
authored
[3.14] gh-132710: only use stable _uuid.generate_time_safe() to deduce MAC address (GH-132901) (#134697)
(cherry picked from commit 3bffada)
1 parent c8379c7 commit 072f50f

File tree

6 files changed

+357
-28
lines changed

6 files changed

+357
-28
lines changed

Lib/test/test_uuid.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from test import support
1616
from test.support import import_helper
17+
from test.support.script_helper import assert_python_ok
1718

1819
py_uuid = import_helper.import_fresh_module('uuid', blocked=['_uuid'])
1920
c_uuid = import_helper.import_fresh_module('uuid', fresh=['_uuid'])
@@ -1217,10 +1218,37 @@ def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self):
12171218
class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase):
12181219
uuid = py_uuid
12191220

1221+
12201222
@unittest.skipUnless(c_uuid, 'requires the C _uuid module')
12211223
class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
12221224
uuid = c_uuid
12231225

1226+
def check_has_stable_libuuid_extractable_node(self):
1227+
if not self.uuid._has_stable_extractable_node:
1228+
self.skipTest("libuuid cannot deduce MAC address")
1229+
1230+
@unittest.skipUnless(os.name == 'posix', 'POSIX only')
1231+
def test_unix_getnode_from_libuuid(self):
1232+
self.check_has_stable_libuuid_extractable_node()
1233+
script = 'import uuid; print(uuid._unix_getnode())'
1234+
_, n_a, _ = assert_python_ok('-c', script)
1235+
_, n_b, _ = assert_python_ok('-c', script)
1236+
n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
1237+
self.assertTrue(n_a.isdigit())
1238+
self.assertTrue(n_b.isdigit())
1239+
self.assertEqual(n_a, n_b)
1240+
1241+
@unittest.skipUnless(os.name == 'nt', 'Windows only')
1242+
def test_windows_getnode_from_libuuid(self):
1243+
self.check_has_stable_libuuid_extractable_node()
1244+
script = 'import uuid; print(uuid._windll_getnode())'
1245+
_, n_a, _ = assert_python_ok('-c', script)
1246+
_, n_b, _ = assert_python_ok('-c', script)
1247+
n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
1248+
self.assertTrue(n_a.isdigit())
1249+
self.assertTrue(n_b.isdigit())
1250+
self.assertEqual(n_a, n_b)
1251+
12241252

12251253
class BaseTestInternals:
12261254
_uuid = py_uuid

Lib/uuid.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,22 +633,24 @@ def _netstat_getnode():
633633
try:
634634
import _uuid
635635
_generate_time_safe = getattr(_uuid, "generate_time_safe", None)
636+
_has_stable_extractable_node = _uuid.has_stable_extractable_node
636637
_UuidCreate = getattr(_uuid, "UuidCreate", None)
637638
except ImportError:
638639
_uuid = None
639640
_generate_time_safe = None
641+
_has_stable_extractable_node = False
640642
_UuidCreate = None
641643

642644

643645
def _unix_getnode():
644646
"""Get the hardware address on Unix using the _uuid extension module."""
645-
if _generate_time_safe:
647+
if _generate_time_safe and _has_stable_extractable_node:
646648
uuid_time, _ = _generate_time_safe()
647649
return UUID(bytes=uuid_time).node
648650

649651
def _windll_getnode():
650652
"""Get the hardware address on Windows using the _uuid extension module."""
651-
if _UuidCreate:
653+
if _UuidCreate and _has_stable_extractable_node:
652654
uuid_bytes = _UuidCreate()
653655
return UUID(bytes_le=uuid_bytes).node
654656

Modules/_uuidmodule.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,47 @@ py_UuidCreate(PyObject *Py_UNUSED(context),
7878
return NULL;
7979
}
8080

81+
static int
82+
py_windows_has_stable_node(void)
83+
{
84+
UUID uuid;
85+
RPC_STATUS res;
86+
Py_BEGIN_ALLOW_THREADS
87+
res = UuidCreateSequential(&uuid);
88+
Py_END_ALLOW_THREADS
89+
return res == RPC_S_OK;
90+
}
8191
#endif /* MS_WINDOWS */
8292

8393

8494
static int
85-
uuid_exec(PyObject *module) {
95+
uuid_exec(PyObject *module)
96+
{
97+
#define ADD_INT(NAME, VALUE) \
98+
do { \
99+
if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \
100+
return -1; \
101+
} \
102+
} while (0)
103+
86104
assert(sizeof(uuid_t) == 16);
87105
#if defined(MS_WINDOWS)
88-
int has_uuid_generate_time_safe = 0;
106+
ADD_INT("has_uuid_generate_time_safe", 0);
89107
#elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
90-
int has_uuid_generate_time_safe = 1;
108+
ADD_INT("has_uuid_generate_time_safe", 1);
91109
#else
92-
int has_uuid_generate_time_safe = 0;
110+
ADD_INT("has_uuid_generate_time_safe", 0);
93111
#endif
94-
if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
95-
has_uuid_generate_time_safe) < 0) {
96-
return -1;
97-
}
112+
113+
#if defined(MS_WINDOWS)
114+
ADD_INT("has_stable_extractable_node", py_windows_has_stable_node());
115+
#elif defined(HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC)
116+
ADD_INT("has_stable_extractable_node", 1);
117+
#else
118+
ADD_INT("has_stable_extractable_node", 0);
119+
#endif
120+
121+
#undef ADD_INT
98122
return 0;
99123
}
100124

0 commit comments

Comments
 (0)