gh-132710: only use stable _uuid.generate_time_safe() to deduce MAC address (#132901)

This commit is contained in:
Bénédikt Tran 2025-05-26 10:56:31 +02:00 committed by GitHub
parent 29e8115964
commit 3bffada467
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 357 additions and 28 deletions

View file

@ -14,6 +14,7 @@ from unittest import mock
from test import support from test import support
from test.support import import_helper from test.support import import_helper
from test.support.script_helper import assert_python_ok
py_uuid = import_helper.import_fresh_module('uuid', blocked=['_uuid']) py_uuid = import_helper.import_fresh_module('uuid', blocked=['_uuid'])
c_uuid = import_helper.import_fresh_module('uuid', fresh=['_uuid']) c_uuid = import_helper.import_fresh_module('uuid', fresh=['_uuid'])
@ -1217,10 +1218,37 @@ class BaseTestUUID:
class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase): class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase):
uuid = py_uuid uuid = py_uuid
@unittest.skipUnless(c_uuid, 'requires the C _uuid module') @unittest.skipUnless(c_uuid, 'requires the C _uuid module')
class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase): class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
uuid = c_uuid uuid = c_uuid
def check_has_stable_libuuid_extractable_node(self):
if not self.uuid._has_stable_extractable_node:
self.skipTest("libuuid cannot deduce MAC address")
@unittest.skipUnless(os.name == 'posix', 'POSIX only')
def test_unix_getnode_from_libuuid(self):
self.check_has_stable_libuuid_extractable_node()
script = 'import uuid; print(uuid._unix_getnode())'
_, n_a, _ = assert_python_ok('-c', script)
_, n_b, _ = assert_python_ok('-c', script)
n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
self.assertTrue(n_a.isdigit())
self.assertTrue(n_b.isdigit())
self.assertEqual(n_a, n_b)
@unittest.skipUnless(os.name == 'nt', 'Windows only')
def test_windows_getnode_from_libuuid(self):
self.check_has_stable_libuuid_extractable_node()
script = 'import uuid; print(uuid._windll_getnode())'
_, n_a, _ = assert_python_ok('-c', script)
_, n_b, _ = assert_python_ok('-c', script)
n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
self.assertTrue(n_a.isdigit())
self.assertTrue(n_b.isdigit())
self.assertEqual(n_a, n_b)
class BaseTestInternals: class BaseTestInternals:
_uuid = py_uuid _uuid = py_uuid

View file

@ -633,22 +633,24 @@ def _netstat_getnode():
try: try:
import _uuid import _uuid
_generate_time_safe = getattr(_uuid, "generate_time_safe", None) _generate_time_safe = getattr(_uuid, "generate_time_safe", None)
_has_stable_extractable_node = _uuid.has_stable_extractable_node
_UuidCreate = getattr(_uuid, "UuidCreate", None) _UuidCreate = getattr(_uuid, "UuidCreate", None)
except ImportError: except ImportError:
_uuid = None _uuid = None
_generate_time_safe = None _generate_time_safe = None
_has_stable_extractable_node = False
_UuidCreate = None _UuidCreate = None
def _unix_getnode(): def _unix_getnode():
"""Get the hardware address on Unix using the _uuid extension module.""" """Get the hardware address on Unix using the _uuid extension module."""
if _generate_time_safe: if _generate_time_safe and _has_stable_extractable_node:
uuid_time, _ = _generate_time_safe() uuid_time, _ = _generate_time_safe()
return UUID(bytes=uuid_time).node return UUID(bytes=uuid_time).node
def _windll_getnode(): def _windll_getnode():
"""Get the hardware address on Windows using the _uuid extension module.""" """Get the hardware address on Windows using the _uuid extension module."""
if _UuidCreate: if _UuidCreate and _has_stable_extractable_node:
uuid_bytes = _UuidCreate() uuid_bytes = _UuidCreate()
return UUID(bytes_le=uuid_bytes).node return UUID(bytes_le=uuid_bytes).node

View file

@ -78,23 +78,47 @@ py_UuidCreate(PyObject *Py_UNUSED(context),
return NULL; return NULL;
} }
static int
py_windows_has_stable_node(void)
{
UUID uuid;
RPC_STATUS res;
Py_BEGIN_ALLOW_THREADS
res = UuidCreateSequential(&uuid);
Py_END_ALLOW_THREADS
return res == RPC_S_OK;
}
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
static int static int
uuid_exec(PyObject *module) { uuid_exec(PyObject *module)
{
#define ADD_INT(NAME, VALUE) \
do { \
if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \
return -1; \
} \
} while (0)
assert(sizeof(uuid_t) == 16); assert(sizeof(uuid_t) == 16);
#if defined(MS_WINDOWS) #if defined(MS_WINDOWS)
int has_uuid_generate_time_safe = 0; ADD_INT("has_uuid_generate_time_safe", 0);
#elif defined(HAVE_UUID_GENERATE_TIME_SAFE) #elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
int has_uuid_generate_time_safe = 1; ADD_INT("has_uuid_generate_time_safe", 1);
#else #else
int has_uuid_generate_time_safe = 0; ADD_INT("has_uuid_generate_time_safe", 0);
#endif #endif
if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
has_uuid_generate_time_safe) < 0) { #if defined(MS_WINDOWS)
return -1; ADD_INT("has_stable_extractable_node", py_windows_has_stable_node());
} #elif defined(HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC)
ADD_INT("has_stable_extractable_node", 1);
#else
ADD_INT("has_stable_extractable_node", 0);
#endif
#undef ADD_INT
return 0; return 0;
} }

209
configure generated vendored
View file

@ -14052,6 +14052,7 @@ fi
have_uuid=missing have_uuid=missing
for ac_header in uuid.h for ac_header in uuid.h
@ -14061,6 +14062,7 @@ if test "x$ac_cv_header_uuid_h" = xyes
then : then :
printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
for ac_func in uuid_create uuid_enc_be for ac_func in uuid_create uuid_enc_be
do : do :
as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"` as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
@ -14070,7 +14072,9 @@ then :
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1 #define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
_ACEOF _ACEOF
have_uuid=yes
have_uuid=yes
ac_cv_have_uuid_h=yes
LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
LIBUUID_LIBS=${LIBUUID_LIBS-""} LIBUUID_LIBS=${LIBUUID_LIBS-""}
@ -14160,6 +14164,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes
then : then :
printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
ac_cv_have_uuid_uuid_h=yes
py_check_lib_save_LIBS=$LIBS py_check_lib_save_LIBS=$LIBS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
printf %s "checking for uuid_generate_time in -luuid... " >&6; } printf %s "checking for uuid_generate_time in -luuid... " >&6; }
@ -14257,8 +14262,9 @@ fi
printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; }
if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes
then : then :
have_uuid=yes
printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h have_uuid=yes
ac_cv_have_uuid_generate_time_safe=yes
fi fi
@ -14302,6 +14308,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes
then : then :
printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
ac_cv_have_uuid_uuid_h=yes
py_check_lib_save_LIBS=$LIBS py_check_lib_save_LIBS=$LIBS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
printf %s "checking for uuid_generate_time in -luuid... " >&6; } printf %s "checking for uuid_generate_time in -luuid... " >&6; }
@ -14399,8 +14406,9 @@ fi
printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; }
if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes
then : then :
have_uuid=yes
printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h have_uuid=yes
ac_cv_have_uuid_generate_time_safe=yes
fi fi
@ -14431,10 +14439,16 @@ else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; } printf "%s\n" "yes" >&6; }
have_uuid=yes have_uuid=yes
printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h ac_cv_have_uuid_generate_time_safe=yes
# The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h # Since pkg-config --cflags uuid may return -I/usr/include/uuid,
# it's possible to write '#include <uuid.h>' in _uuidmodule.c,
# assuming that the compiler flags are properly updated.
#
# Ideally, we should have defined HAVE_UUID_H if and only if
# #include <uuid.h> can be written, *without* assuming extra
# include path.
ac_cv_have_uuid_h=yes
fi fi
@ -14455,6 +14469,7 @@ if test "x$ac_cv_func_uuid_generate_time" = xyes
then : then :
have_uuid=yes have_uuid=yes
ac_cv_have_uuid_uuid_h=yes
LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
LIBUUID_LIBS=${LIBUUID_LIBS-""} LIBUUID_LIBS=${LIBUUID_LIBS-""}
@ -14465,6 +14480,24 @@ fi
done done
fi
if test "x$ac_cv_have_uuid_h" = xyes
then :
printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
fi
if test "x$ac_cv_have_uuid_uuid_h" = xyes
then :
printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
fi
if test "x$ac_cv_have_uuid_generate_time_safe" = xyes
then :
printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
fi fi
# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4. # gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4.
@ -14480,6 +14513,164 @@ then :
have_uuid=no have_uuid=no
fi fi
# gh-132710: The UUID node is fetched by using libuuid when possible
# and cached. While the node is constant within the same process,
# different interpreters may have different values as libuuid may
# randomize the node value if the latter cannot be deduced.
#
# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
# to indicate that libuuid is unstable and should not be relied
# upon to deduce the MAC address.
if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1"
then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if uuid_generate_time_safe() node value is stable" >&5
printf %s "checking if uuid_generate_time_safe() node value is stable... " >&6; }
save_CFLAGS=$CFLAGS
save_CPPFLAGS=$CPPFLAGS
save_LDFLAGS=$LDFLAGS
save_LIBS=$LIBS
# Be sure to add the extra include path if we used pkg-config
# as HAVE_UUID_H may be set even though <uuid.h> is only reachable
# by adding extra -I flags.
#
# If the following script does not compile, we simply assume that
# libuuid is missing.
CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
LIBS="$LIBS $LIBUUID_LIBS"
if test "$cross_compiling" = yes
then :
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <inttypes.h> // PRIu64
#include <stdint.h> // uint64_t
#include <stdio.h> // fopen(), fclose()
#ifdef HAVE_UUID_H
#include <uuid.h>
#else
#include <uuid/uuid.h>
#endif
#define ERR 1
int main(void) {
uuid_t uuid; // unsigned char[16]
(void)uuid_generate_time_safe(uuid);
uint64_t node = 0;
for (size_t i = 0; i < 6; i++) {
node |= (uint64_t)uuid[15 - i] << (8 * i);
}
FILE *fp = fopen("conftest.out", "w");
if (fp == NULL) {
return ERR;
}
int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
rc |= fclose(fp);
return rc == 0 ? 0 : ERR;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"
then :
py_cv_uuid_node1=`cat conftest.out`
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
CFLAGS=$save_CFLAGS
CPPFLAGS=$save_CPPFLAGS
LDFLAGS=$save_LDFLAGS
LIBS=$save_LIBS
save_CFLAGS=$CFLAGS
save_CPPFLAGS=$CPPFLAGS
save_LDFLAGS=$LDFLAGS
save_LIBS=$LIBS
# Be sure to add the extra include path if we used pkg-config
# as HAVE_UUID_H may be set even though <uuid.h> is only reachable
# by adding extra -I flags.
#
# If the following script does not compile, we simply assume that
# libuuid is missing.
CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
LIBS="$LIBS $LIBUUID_LIBS"
if test "$cross_compiling" = yes
then :
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <inttypes.h> // PRIu64
#include <stdint.h> // uint64_t
#include <stdio.h> // fopen(), fclose()
#ifdef HAVE_UUID_H
#include <uuid.h>
#else
#include <uuid/uuid.h>
#endif
#define ERR 1
int main(void) {
uuid_t uuid; // unsigned char[16]
(void)uuid_generate_time_safe(uuid);
uint64_t node = 0;
for (size_t i = 0; i < 6; i++) {
node |= (uint64_t)uuid[15 - i] << (8 * i);
}
FILE *fp = fopen("conftest.out", "w");
if (fp == NULL) {
return ERR;
}
int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
rc |= fclose(fp);
return rc == 0 ? 0 : ERR;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"
then :
py_cv_uuid_node2=`cat conftest.out`
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
CFLAGS=$save_CFLAGS
CPPFLAGS=$save_CPPFLAGS
LDFLAGS=$save_LDFLAGS
LIBS=$save_LIBS
if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2"
then
printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC 1" >>confdefs.h
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: stable" >&5
printf "%s\n" "stable" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unstable" >&5
printf "%s\n" "unstable" >&6; }
fi
fi
# 'Real Time' functions on Solaris # 'Real Time' functions on Solaris
# posix4 on Solaris 2.6 # posix4 on Solaris 2.6
# pthread (first!) on Linux # pthread (first!) on Linux

View file

@ -3740,15 +3740,17 @@ dnl check for uuid dependencies
AH_TEMPLATE([HAVE_UUID_H], [Define to 1 if you have the <uuid.h> header file.]) AH_TEMPLATE([HAVE_UUID_H], [Define to 1 if you have the <uuid.h> header file.])
AH_TEMPLATE([HAVE_UUID_UUID_H], [Define to 1 if you have the <uuid/uuid.h> header file.]) AH_TEMPLATE([HAVE_UUID_UUID_H], [Define to 1 if you have the <uuid/uuid.h> header file.])
AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE], [Define if uuid_generate_time_safe() exists.]) AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE], [Define if uuid_generate_time_safe() exists.])
AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [Define if uuid_generate_time_safe() is able to deduce a MAC address.])
have_uuid=missing have_uuid=missing
dnl AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 dnl AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1
dnl (anno 2007). FreeBSD and OpenBSD provides support in libc as well. dnl (anno 2007). FreeBSD and OpenBSD provides support in libc as well.
dnl Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet dnl Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet
dnl stream in big-endian byte-order dnl stream in big-endian byte-order
AC_CHECK_HEADERS([uuid.h], AC_CHECK_HEADERS([uuid.h], [
[AC_CHECK_FUNCS([uuid_create uuid_enc_be], AC_CHECK_FUNCS([uuid_create uuid_enc_be], [
[have_uuid=yes have_uuid=yes
ac_cv_have_uuid_h=yes
LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
LIBUUID_LIBS=${LIBUUID_LIBS-""} LIBUUID_LIBS=${LIBUUID_LIBS-""}
]) ])
@ -3758,19 +3760,29 @@ AS_VAR_IF([have_uuid], [missing], [
PKG_CHECK_MODULES( PKG_CHECK_MODULES(
[LIBUUID], [uuid >= 2.20], [LIBUUID], [uuid >= 2.20],
[dnl linux-util's libuuid has uuid_generate_time_safe() since v2.20 (2011) [dnl linux-util's libuuid has uuid_generate_time_safe() since v2.20 (2011)
dnl and provides <uuid.h>. dnl and provides <uuid.h> assuming specific include paths are given
have_uuid=yes have_uuid=yes
AC_DEFINE([HAVE_UUID_H], [1]) ac_cv_have_uuid_generate_time_safe=yes
AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) # The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
# Since pkg-config --cflags uuid may return -I/usr/include/uuid,
# it's possible to write '#include <uuid.h>' in _uuidmodule.c,
# assuming that the compiler flags are properly updated.
#
# Ideally, we should have defined HAVE_UUID_H if and only if
# #include <uuid.h> can be written, *without* assuming extra
# include path.
ac_cv_have_uuid_h=yes
], [ ], [
WITH_SAVE_ENV([ WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS" CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS"
LIBS="$LIBS $LIBUUID_LIBS" LIBS="$LIBS $LIBUUID_LIBS"
AC_CHECK_HEADERS([uuid/uuid.h], [ AC_CHECK_HEADERS([uuid/uuid.h], [
ac_cv_have_uuid_uuid_h=yes
PY_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes]) PY_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes])
PY_CHECK_LIB([uuid], [uuid_generate_time_safe], PY_CHECK_LIB([uuid], [uuid_generate_time_safe], [
[have_uuid=yes have_uuid=yes
AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ]) ]) ac_cv_have_uuid_generate_time_safe=yes
])])
AS_VAR_IF([have_uuid], [yes], [ AS_VAR_IF([have_uuid], [yes], [
LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"} LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"}
@ -3785,12 +3797,19 @@ AS_VAR_IF([have_uuid], [missing], [
AC_CHECK_HEADERS([uuid/uuid.h], [ AC_CHECK_HEADERS([uuid/uuid.h], [
AC_CHECK_FUNC([uuid_generate_time], [ AC_CHECK_FUNC([uuid_generate_time], [
have_uuid=yes have_uuid=yes
ac_cv_have_uuid_uuid_h=yes
LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
LIBUUID_LIBS=${LIBUUID_LIBS-""} LIBUUID_LIBS=${LIBUUID_LIBS-""}
]) ])
]) ])
]) ])
AS_VAR_IF([ac_cv_have_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_H], [1])])
AS_VAR_IF([ac_cv_have_uuid_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_UUID_H], [1])])
AS_VAR_IF([ac_cv_have_uuid_generate_time_safe], [yes], [
AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1])
])
# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4. # gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4.
# This restriction inhibits the proper generation of time-based UUIDs. # This restriction inhibits the proper generation of time-based UUIDs.
if test "$ac_sys_system" = "NetBSD"; then if test "$ac_sys_system" = "NetBSD"; then
@ -3800,6 +3819,68 @@ fi
AS_VAR_IF([have_uuid], [missing], [have_uuid=no]) AS_VAR_IF([have_uuid], [missing], [have_uuid=no])
# gh-132710: The UUID node is fetched by using libuuid when possible
# and cached. While the node is constant within the same process,
# different interpreters may have different values as libuuid may
# randomize the node value if the latter cannot be deduced.
#
# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
# to indicate that libuuid is unstable and should not be relied
# upon to deduce the MAC address.
AC_DEFUN([PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC], [WITH_SAVE_ENV([
# Be sure to add the extra include path if we used pkg-config
# as HAVE_UUID_H may be set even though <uuid.h> is only reachable
# by adding extra -I flags.
#
# If the following script does not compile, we simply assume that
# libuuid is missing.
CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
LIBS="$LIBS $LIBUUID_LIBS"
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <inttypes.h> // PRIu64
#include <stdint.h> // uint64_t
#include <stdio.h> // fopen(), fclose()
#ifdef HAVE_UUID_H
#include <uuid.h>
#else
#include <uuid/uuid.h>
#endif
#define ERR 1
int main(void) {
uuid_t uuid; // unsigned char[16]
(void)uuid_generate_time_safe(uuid);
uint64_t node = 0;
for (size_t i = 0; i < 6; i++) {
node |= (uint64_t)uuid[15 - i] << (8 * i);
}
FILE *fp = fopen("conftest.out", "w");
if (fp == NULL) {
return ERR;
}
int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
rc |= fclose(fp);
return rc == 0 ? 0 : ERR;
}]])], [
AS_VAR_SET([$1], [`cat conftest.out`])
], [], []
)])])
if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1"
then
AC_MSG_CHECKING([if uuid_generate_time_safe() node value is stable])
PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node1])
PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node2])
if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2"
then
AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [1])
AC_MSG_RESULT([stable])
else
AC_MSG_RESULT([unstable])
fi
fi
# 'Real Time' functions on Solaris # 'Real Time' functions on Solaris
# posix4 on Solaris 2.6 # posix4 on Solaris 2.6
# pthread (first!) on Linux # pthread (first!) on Linux

View file

@ -1584,6 +1584,9 @@
/* Define if uuid_generate_time_safe() exists. */ /* Define if uuid_generate_time_safe() exists. */
#undef HAVE_UUID_GENERATE_TIME_SAFE #undef HAVE_UUID_GENERATE_TIME_SAFE
/* Define if uuid_generate_time_safe() is able to deduce a MAC address. */
#undef HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
/* Define to 1 if you have the <uuid.h> header file. */ /* Define to 1 if you have the <uuid.h> header file. */
#undef HAVE_UUID_H #undef HAVE_UUID_H