Fix saving 4GB+ files file size cutting off issue

This commit fixes invalid 64-bit to 32-bit castings of filesize integers.

Fix #12526, close #12736
This commit is contained in:
xomx 2022-12-31 03:29:40 +01:00 committed by Don Ho
parent 307fd2fcd2
commit c63c0035f3
5 changed files with 36 additions and 13 deletions

View File

@ -122,15 +122,38 @@ unsigned long Win32_IO_File::read(void *rbuf, unsigned long buf_size)
} }
*/ */
bool Win32_IO_File::write(const void *wbuf, unsigned long buf_size) bool Win32_IO_File::write(const void *wbuf, size_t buf_size)
{ {
if (!isOpened() || (wbuf == nullptr)) if (!isOpened() || (wbuf == nullptr))
return false; return false;
DWORD bytes_written = 0; // we need to split any 4GB+ data for the WriteFile WINAPI later
constexpr DWORD c_max_dword = ~(DWORD(0)); // 0xFFFFFFFF
size_t total_bytes_written = 0;
size_t bytes_left_to_write = buf_size;
BOOL success = FALSE;
do
{
const DWORD bytes_to_write = (bytes_left_to_write < static_cast<size_t>(c_max_dword)) ?
static_cast<DWORD>(bytes_left_to_write) : c_max_dword;
DWORD bytes_written = 0;
success = ::WriteFile(_hFile, static_cast<const char*>(wbuf) + total_bytes_written,
bytes_to_write, &bytes_written, NULL);
if (success)
{
success = (bytes_written == bytes_to_write);
bytes_left_to_write -= static_cast<size_t>(bytes_written);
total_bytes_written += static_cast<size_t>(bytes_written);
}
} while (success && bytes_left_to_write);
NppParameters& nppParam = NppParameters::getInstance(); NppParameters& nppParam = NppParameters::getInstance();
if (::WriteFile(_hFile, wbuf, buf_size, &bytes_written, NULL) == FALSE)
if (success == FALSE)
{ {
if (nppParam.isEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue()) if (nppParam.isEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
{ {
@ -160,7 +183,7 @@ bool Win32_IO_File::write(const void *wbuf, unsigned long buf_size)
std::string msg = _path; std::string msg = _path;
msg += " "; msg += " ";
msg += std::to_string(bytes_written); msg += std::to_string(total_bytes_written);
msg += "/"; msg += "/";
msg += std::to_string(buf_size); msg += std::to_string(buf_size);
msg += " bytes are written."; msg += " bytes are written.";
@ -171,6 +194,6 @@ bool Win32_IO_File::write(const void *wbuf, unsigned long buf_size)
if (!_written) if (!_written)
_written = true; _written = true;
return (bytes_written == buf_size); return (total_bytes_written == buf_size);
} }

View File

@ -45,10 +45,10 @@ public:
//int_fast64_t getSize(); //int_fast64_t getSize();
//unsigned long read(void *rbuf, unsigned long buf_size); //unsigned long read(void *rbuf, unsigned long buf_size);
bool write(const void *wbuf, unsigned long buf_size); bool write(const void *wbuf, size_t buf_size);
bool writeStr(const std::string& str) { bool writeStr(const std::string& str) {
return write(str.c_str(), static_cast<unsigned long>(str.length())); return write(str.c_str(), str.length());
}; };
private: private:

View File

@ -1036,7 +1036,7 @@ bool FileManager::backupCurrentBuffer()
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
{ {
isWrittenSuccessful = UnicodeConvertor.writeFile(buf, static_cast<unsigned long>(lengthDoc)); isWrittenSuccessful = UnicodeConvertor.writeFile(buf, lengthDoc);
if (lengthDoc == 0) if (lengthDoc == 0)
isWrittenSuccessful = true; isWrittenSuccessful = true;
} }
@ -1054,7 +1054,7 @@ bool FileManager::backupCurrentBuffer()
int incompleteMultibyteChar = 0; int incompleteMultibyteChar = 0;
const char *newData = wmc.encode(SC_CP_UTF8, encoding, buf+i, static_cast<int>(grabSize), &newDataLen, &incompleteMultibyteChar); const char *newData = wmc.encode(SC_CP_UTF8, encoding, buf+i, static_cast<int>(grabSize), &newDataLen, &incompleteMultibyteChar);
grabSize -= incompleteMultibyteChar; grabSize -= incompleteMultibyteChar;
isWrittenSuccessful = UnicodeConvertor.writeFile(newData, static_cast<unsigned long>(newDataLen)); isWrittenSuccessful = UnicodeConvertor.writeFile(newData, newDataLen);
} }
if (lengthDoc == 0) if (lengthDoc == 0)
isWrittenSuccessful = true; isWrittenSuccessful = true;
@ -1170,7 +1170,7 @@ SavingStatus FileManager::saveBuffer(BufferID id, const TCHAR * filename, bool i
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
{ {
isWrittenSuccessful = UnicodeConvertor.writeFile(buf, static_cast<unsigned long>(lengthDoc)); isWrittenSuccessful = UnicodeConvertor.writeFile(buf, lengthDoc);
if (lengthDoc == 0) if (lengthDoc == 0)
isWrittenSuccessful = true; isWrittenSuccessful = true;
} }
@ -1194,7 +1194,7 @@ SavingStatus FileManager::saveBuffer(BufferID id, const TCHAR * filename, bool i
int incompleteMultibyteChar = 0; int incompleteMultibyteChar = 0;
const char* newData = wmc.encode(SC_CP_UTF8, encoding, buf + i, static_cast<int>(grabSize), &newDataLen, &incompleteMultibyteChar); const char* newData = wmc.encode(SC_CP_UTF8, encoding, buf + i, static_cast<int>(grabSize), &newDataLen, &incompleteMultibyteChar);
grabSize -= incompleteMultibyteChar; grabSize -= incompleteMultibyteChar;
isWrittenSuccessful = UnicodeConvertor.writeFile(newData, static_cast<unsigned long>(newDataLen)); isWrittenSuccessful = UnicodeConvertor.writeFile(newData, newDataLen);
} }
} }
} }

View File

@ -299,7 +299,7 @@ bool Utf8_16_Write::openFile(const TCHAR *name)
return true; return true;
} }
bool Utf8_16_Write::writeFile(const void* p, unsigned long _size) bool Utf8_16_Write::writeFile(const void* p, size_t _size)
{ {
// no file open // no file open
if (!m_pFile) if (!m_pFile)

View File

@ -140,7 +140,7 @@ public:
void setEncoding(UniMode eType); void setEncoding(UniMode eType);
bool openFile(const TCHAR *name); bool openFile(const TCHAR *name);
bool writeFile(const void* p, unsigned long _size); bool writeFile(const void* p, size_t _size);
void closeFile(); void closeFile();
size_t convert(char* p, size_t _size); size_t convert(char* p, size_t _size);