From cd491ac07de361c46450bd98f57c8a5c267fa41a Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 2 Feb 2025 13:13:20 +0100 Subject: [PATCH] dict: Handle ENOSYS from getentropy gracefully Also add some comments. Should fix #854. --- dict.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/dict.c b/dict.c index ccd8b5428..5654be315 100644 --- a/dict.c +++ b/dict.c @@ -929,10 +929,13 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { #define WIN32_LEAN_AND_MEAN #include #include -#elif HAVE_DECL_GETENTROPY - #include - #include #else + #if HAVE_DECL_GETENTROPY + /* POSIX 2024 */ + #include + /* Older platforms */ + #include + #endif #include #endif @@ -954,24 +957,50 @@ xmlInitRandom(void) { #ifdef _WIN32 NTSTATUS status; + /* + * You can find many (recent as of 2025) discussions how + * to get a pseudo-random seed on Windows in projects like + * Golang, Rust, Chromium and Firefox. + * + * TODO: Support ProcessPrng available since Windows 10. + */ status = BCryptGenRandom(NULL, (unsigned char *) globalRngState, sizeof(globalRngState), BCRYPT_USE_SYSTEM_PREFERRED_RNG); if (!BCRYPT_SUCCESS(status)) xmlAbort("libxml2: BCryptGenRandom failed with error code %lu\n", GetLastError()); -#elif HAVE_DECL_GETENTROPY +#else + int var; + +#if HAVE_DECL_GETENTROPY while (1) { if (getentropy(globalRngState, sizeof(globalRngState)) == 0) + return; + + /* + * This most likely means that libxml2 was compiled on + * a system supporting certain system calls and is running + * on a system that doesn't support these calls, as can + * be the case on Linux. + */ + if (errno == ENOSYS) break; + /* + * We really don't want to fallback to the unsafe PRNG + * for possibly accidental reasons, so we abort on any + * unknown error. + */ if (errno != EINTR) xmlAbort("libxml2: getentropy failed with error code %d\n", errno); } -#else - int var; +#endif + /* + * TODO: Fallback to /dev/urandom for older POSIX systems. + */ globalRngState[0] = (unsigned) time(NULL) ^ HASH_ROL((unsigned) ((size_t) &xmlInitRandom & 0xFFFFFFFF), 8);