diff --git a/expat/configure.ac b/expat/configure.ac index 75b6500f..5ae840fe 100644 --- a/expat/configure.ac +++ b/expat/configure.ac @@ -99,6 +99,23 @@ AC_C_CONST AC_TYPE_SIZE_T AC_CHECK_FUNCS(memmove bcopy) + +AC_MSG_CHECKING([for getrandom (Linux 3.17+, glibc 2.25+)]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + #include /* for NULL */ + #include + int main() { + return getrandom(NULL, 0U, 0U); + } +])], [ + AC_DEFINE([HAVE_GETRANDOM], [1], + [Define to 1 if you have the `getrandom' function.]) + AC_MSG_RESULT([yes]) +], [ + AC_MSG_RESULT([no]) +]) + + dnl Only needed for xmlwf: AC_CHECK_HEADERS(fcntl.h unistd.h) AC_TYPE_OFF_T diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c index 177b0b5f..af3c7890 100644 --- a/expat/lib/xmlparse.c +++ b/expat/lib/xmlparse.c @@ -698,6 +698,36 @@ static const XML_Char implicitContext[] = { }; +#if defined(HAVE_GETRANDOM) +# include +# include + +/* Obtain entropy on Linux 3.17+ with glibc 2.25+ */ +static int +writeRandomBytes_getrandom(void * target, size_t count) { + int success = 0; /* full count bytes written? */ + size_t bytesWrittenTotal = 0; + const unsigned int getrandomFlags = 0; + + do { + void * const currentTarget = (void*)((char*)target + bytesWrittenTotal); + const size_t bytesToWrite = count - bytesWrittenTotal; + + const int bytesWrittenMore + = getrandom(currentTarget, bytesToWrite, getrandomFlags); + if (bytesWrittenMore > 0) { + bytesWrittenTotal += bytesWrittenMore; + if (bytesWrittenTotal >= count) + success = 1; + } + } while (! success && (errno == EINTR || errno == EAGAIN)); + + return success; +} + +#endif /* defined(HAVE_GETRANDOM) */ + + #ifdef _WIN32 typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG); @@ -774,6 +804,10 @@ generate_hash_secret_salt(XML_Parser parser) if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) { return entropy; } +#elif defined(HAVE_GETRANDOM) + if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) { + return entropy; + } #endif /* .. and self-made low quality for backup: */