Opened 14 months ago
Last modified 14 months ago
#21967 new defect
Memory Mapped file not flushed to disk file located on Host Shared Folder - Windows Guest
Reported by: | ron[ny] | Owned by: | |
---|---|---|---|
Component: | shared folders | Version: | VirtualBox-7.0.14 |
Keywords: | Cc: | ron[ny] | |
Guest type: | Windows | Host type: | Mac OS X |
Description
Summary:
Discovered when using the LLVM toolchain to compile and link executables targeted to reside on a VirtualBox shared folder, the resulting executable had the correct size but consisted of only null bytes. Subsequent review with LLVM-MingW owner revealed that adding an explicit call to FlushFileBuffers() solves the bug.
Environment:
Host OS: [MacOS 14.1.1] VirtualBox Version: [7.0.14] Guest OS: [Window 11 Pro 22H2 Build: 22621.3007]
Steps to Reproduce:
Set up a shared folder in VirtualBox. Use the following minimal example code to replicate the behavior of the LLD linker:
#include <windows.h> #include <stdio.h> #include <tchar.h> // Include for TCHAR and related functions void PrintLastError(int line) { DWORD errorMessageID = GetLastError(); if(errorMessageID == 0) { _tprintf(_T("Operation successful.\n")); return; } LPTSTR messageBuffer = NULL; size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&messageBuffer, 0, NULL); _tprintf(_T("Line: %d Error code %lu: %s\n"), line, errorMessageID, messageBuffer); LocalFree(messageBuffer); } int main() { TCHAR tempFilePath[MAX_PATH] = _T("Z:\\test.exe.tmp"); wchar_t finalFilePath[MAX_PATH] = L"Z:\\test.exe"; // Create a file HANDLE hFile = CreateFile(tempFilePath, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { PrintLastError(__LINE__); return 1; } // Create a file mapping object HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 1024, NULL); if (hMapFile == NULL) { PrintLastError(__LINE__); CloseHandle(hFile); return 1; } // Map a view of the file into the address space LPVOID pMapView = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024); if (pMapView == NULL) { PrintLastError(__LINE__); CloseHandle(hMapFile); CloseHandle(hFile); return 1; } // Close the mapping handle; the mapping is still kept open. CloseHandle(hMapFile); // Write to the memory area const char data[] = "Sample Data"; memcpy(pMapView, data, sizeof(data)); // Unmap the file UnmapViewOfFile(pMapView); // FlushFileBuffers(hFile); char buf[sizeof(FILE_RENAME_INFO) + sizeof(wchar_t)*100]; FILE_RENAME_INFO *rename = (FILE_RENAME_INFO*)buf; rename->ReplaceIfExists = 1; rename->RootDirectory = 0; rename->FileNameLength = wcslen(finalFilePath) * sizeof(wchar_t); memcpy(rename->FileName, finalFilePath, wcslen(finalFilePath) * sizeof(wchar_t)); // Rename with SetFileInformationByHandle(FileRenameInfo) if (!SetFileInformationByHandle(hFile, FileRenameInfo, buf, sizeof(buf))) { PrintLastError(__LINE__); CloseHandle(hFile); return 1; } CloseHandle(hFile); _tprintf(_T("File operation completed successfully.") ); return 0; }
Expected Behavior:
The sample target file should be created with the specified data written to it.
Actual Behavior:
The target file is of the right size but consists entirely of null bytes.
Additional Information:
This issue was initially reported to the LLVM-Mingw project (https://github.com/mstorsjo/llvm-mingw/issues/393). It was confirmed by the LLVM-MingW owner and replicated with a reduced sample.
The issue has been reported to the LLVM project and a workaround this bug is being addressed in a pull request (https://github.com/llvm/llvm-project/pull/78597).
It was suggested by the maintainer of LLVM-Mingw to report this issue to VirtualBox Bug Tracker, as it was not replicable on other virtualization software.
Potential Impact:
This issue impacts developers who compile and link using LLVM's LLD on VirtualBox shared folders, as well as anyone using memory mapped files in a similar way to the LLD executable linkage process (examplified by the attached reduced sample). potentially affecting a range of development and testing scenarios.
Attachments (1)
Change History (3)
by , 14 months ago
Attachment: | testkeep.cpp added |
---|
comment:1 by , 14 months ago
comment:2 by , 14 months ago
Not at all - in my case I have no problem, compiling, linking, and running exeutables on that same network drive. The only issue is this very specific case, i.e. memory mapped file NOT COMMITTED to disk, as used in the LLD workflow and thus appearing if one uses LLVM toolchain targeting such VM shared folder on a Windows guest.
I don't know if it plays any role in your issue, but after skimming over your LLVM-Mingw issue thread, I think that the following perhaps might interest you:
For many years now, there has been a VirtualBox issue that prevents a Windows guest from running executables located in VirtualBox Shared Folders, giving the apparently wrong error message "The specified path does not exist". This only happens when using drive letter mappings (e.g. Z:), but not when using UNC paths. Two years ago, a user (and later myself) discovered that the length of the share name and the fully qualified file name in the guest play a tricky role (see #20702 for the gory details).
As an idea, could you replace any occurrence of drive letter mappings by UNC paths for a test?