Skip to content

Commit 3c37483

Browse files
authored
[3.13] pythongh-132710: only use stable _uuid.generate_time_safe() to deduce MAC address (pythonGH-132901) (python#134704)
This commit includes the original commit and the NEWS entry that was added separately. (cherry picked from commit 3bffada) (cherry picked from commit 9eb84d8)
1 parent 932221b commit 3c37483

File tree

7 files changed

+373
-28
lines changed

7 files changed

+373
-28
lines changed

Lib/test/test_uuid.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import unittest
22
from test import support
33
from test.support import import_helper
4+
from test.support.script_helper import assert_python_ok
45
import builtins
56
import contextlib
67
import copy
@@ -773,10 +774,37 @@ def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self):
773774
class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase):
774775
uuid = py_uuid
775776

777+
776778
@unittest.skipUnless(c_uuid, 'requires the C _uuid module')
777779
class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
778780
uuid = c_uuid
779781

782+
def check_has_stable_libuuid_extractable_node(self):
783+
if not self.uuid._has_stable_extractable_node:
784+
self.skipTest("libuuid cannot deduce MAC address")
785+
786+
@unittest.skipUnless(os.name == 'posix', 'POSIX only')
787+
def test_unix_getnode_from_libuuid(self):
788+
self.check_has_stable_libuuid_extractable_node()
789+
script = 'import uuid; print(uuid._unix_getnode())'
790+
_, n_a, _ = assert_python_ok('-c', script)
791+
_, n_b, _ = assert_python_ok('-c', script)
792+
n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
793+
self.assertTrue(n_a.isdigit())
794+
self.assertTrue(n_b.isdigit())
795+
self.assertEqual(n_a, n_b)
796+
797+
@unittest.skipUnless(os.name == 'nt', 'Windows only')
798+
def test_windows_getnode_from_libuuid(self):
799+
self.check_has_stable_libuuid_extractable_node()
800+
script = 'import uuid; print(uuid._windll_getnode())'
801+
_, n_a, _ = assert_python_ok('-c', script)
802+
_, n_b, _ = assert_python_ok('-c', script)
803+
n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
804+
self.assertTrue(n_a.isdigit())
805+
self.assertTrue(n_b.isdigit())
806+
self.assertEqual(n_a, n_b)
807+
780808

781809
class BaseTestInternals:
782810
_uuid = py_uuid

Lib/uuid.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,22 +572,24 @@ def _netstat_getnode():
572572
try:
573573
import _uuid
574574
_generate_time_safe = getattr(_uuid, "generate_time_safe", None)
575+
_has_stable_extractable_node = getattr(_uuid, "has_stable_extractable_node", False)
575576
_UuidCreate = getattr(_uuid, "UuidCreate", None)
576577
except ImportError:
577578
_uuid = None
578579
_generate_time_safe = None
580+
_has_stable_extractable_node = False
579581
_UuidCreate = None
580582

581583

582584
def _unix_getnode():
583585
"""Get the hardware address on Unix using the _uuid extension module."""
584-
if _generate_time_safe:
586+
if _generate_time_safe and _has_stable_extractable_node:
585587
uuid_time, _ = _generate_time_safe()
586588
return UUID(bytes=uuid_time).node
587589

588590
def _windll_getnode():
589591
"""Get the hardware address on Windows using the _uuid extension module."""
590-
if _UuidCreate:
592+
if _UuidCreate and _has_stable_extractable_node:
591593
uuid_bytes = _UuidCreate()
592594
return UUID(bytes_le=uuid_bytes).node
593595

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
If possible, ensure that :func:`uuid.getnode` returns the same result even
2+
across different processes. Previously, the result was constant only within
3+
the same process. Patch by Bénédikt Tran.

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)