From cf3e31ec90e47d988840759e5d755a9460e192ff Mon Sep 17 00:00:00 2001 From: Gabriel Nagy Date: Fri, 25 Sep 2020 16:38:01 +0300 Subject: [PATCH] Fix segfault if high-entropy 64-bit ASLR is enabled If the High-entropy ASLR setting is enabled on Windows, `win32/dir` will segfault when calling `SHGetFileInfo`. Enabling high-entropy ASLR will cause processes to use the entire 64-bit address space, and the `long` data type is not large enough to hold a 64-bit address for the PIDL structure (which is the first argument of `SHGetFileInfo`[1]). As a result, the call segfaults. Change the parameter's data type to `uint64` to ensure that the address will always fit. [1] https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shgetfileinfow Signed-off-by: Gabriel Nagy --- lib/win32/dir.rb | 11 +++++++++-- lib/win32/dir/functions.rb | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/win32/dir.rb b/lib/win32/dir.rb index e3c9921..f2d5644 100644 --- a/lib/win32/dir.rb +++ b/lib/win32/dir.rb @@ -78,12 +78,19 @@ class Dir elsif SHGetFolderPathW(0, value, 0, 1, buf) == 0 # Default path path = buf.strip else - ptr = FFI::MemoryPointer.new(:long) + ptr = FFI::MemoryPointer.new(:uint64) info = SHFILEINFO.new flags = SHGFI_DISPLAYNAME | SHGFI_PIDL if SHGetFolderLocation(0, value, 0, 0, ptr) == 0 - if SHGetFileInfo(ptr.read_long, 0, info, info.size, flags) != 0 + # Use read_array_of_uint64 for compatibility with JRuby if necessary. + if ptr.respond_to?(:read_uint64) + res = SHGetFileInfo(ptr.read_uint64, 0, info, info.size, flags) + else + res = SHGetFileInfo(ptr.read_array_of_uint64(1).first, 0, info, info.size, flags) + end + + if res != 0 path = info[:szDisplayName].to_s path.force_encoding(Encoding.default_external) end diff --git a/lib/win32/dir/functions.rb b/lib/win32/dir/functions.rb index 094f4b1..ecb52c9 100644 --- a/lib/win32/dir/functions.rb +++ b/lib/win32/dir/functions.rb @@ -27,7 +27,7 @@ def attach_pfunc(*args) attach_pfunc :SHGetFolderPathW, %i{hwnd int handle dword buffer_out}, :dword attach_pfunc :SHGetFolderLocation, %i{hwnd int handle dword ptr}, :dword - attach_pfunc :SHGetFileInfo, %i{dword dword ptr uint uint}, :dword + attach_pfunc :SHGetFileInfo, %i{uint64 dword ptr uint uint}, :dword ffi_lib :shlwapi ffi_convention :stdcall