From 24240ed577229eb9568fd8050b9ca4233be92116 Mon Sep 17 00:00:00 2001 From: Daniela Engert Date: Tue, 11 Apr 2017 19:07:53 +0200 Subject: [PATCH] Initialize function pointers at first use. The former global static initialization suffers from the unspecified total initialization order after linking. If other statics call functions which require these function pointers to be initialized, these calls may cause null pointer exceptions. Signed-off-by: Daniela Engert --- src/operations.cpp | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/operations.cpp b/src/operations.cpp index 4114e02a..bea1c68c 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -548,9 +548,7 @@ namespace /*_In_*/ BOOLEAN CaseInSensitive ); - PtrRtlEqualUnicodeString rtl_equal_unicode_string_api = PtrRtlEqualUnicodeString( - ::GetProcAddress( - ::GetModuleHandleW(L"ntdll.dll"), "RtlEqualUnicodeString")); + PtrRtlEqualUnicodeString rtl_equal_unicode_string_api; #ifndef LOCALE_INVARIANT # define LOCALE_INVARIANT (MAKELCID(MAKELANGID(LANG_INVARIANT, SUBLANG_NEUTRAL), SORT_DEFAULT)) @@ -614,9 +612,35 @@ namespace typedef bool (*Ptr_equal_string_ordinal_ic)(const wchar_t*, const wchar_t*); - Ptr_equal_string_ordinal_ic equal_string_ordinal_ic = - rtl_equal_unicode_string_api ? equal_string_ordinal_ic_1 : equal_string_ordinal_ic_2; - + BOOST_NOINLINE Ptr_equal_string_ordinal_ic get_compare_function() + { + rtl_equal_unicode_string_api = PtrRtlEqualUnicodeString( + ::GetProcAddress( + ::GetModuleHandleW(L"ntdll.dll"), "RtlEqualUnicodeString")); + + return rtl_equal_unicode_string_api ? equal_string_ordinal_ic_1 + : equal_string_ordinal_ic_2; + } + + static Ptr_equal_string_ordinal_ic compare_function; + + inline Ptr_equal_string_ordinal_ic compare() + { + if (!compare_function) + { + compare_function = get_compare_function(); + } + return compare_function; + } + + // force function pointer setup into initialization phase + static bool compare_function_initializer = compare() != 0; + + inline bool equal_string_ordinal_ic(const wchar_t* s1, const wchar_t* s2) + { + return compare()(s1, s2); + } + perms make_permissions(const path& p, DWORD attr) { perms prms = fs::owner_read | fs::group_read | fs::others_read;