From 6adc3b35fca36b73a02520ae303ef305d996debc Mon Sep 17 00:00:00 2001 From: milipili Date: Sat, 30 May 2015 20:32:33 +0200 Subject: [PATCH] scintilla: buffer: fixed invalid read in the stack when loading a file The method `FileManager::loadFileData` uses a stack-based buffer for reading a file. However, due to the optimization used by `Utf8_16_Read` (`UnicodeConvertor`), this buffer is not copied, but a pointer to this object is kept. After `loadFileData`, this object is destroyed, but is used afterward (via `UnicodeConvertor.getNewBuf`). --- PowerEditor/src/ScitillaComponent/Buffer.cpp | 24 ++++++++++++-------- PowerEditor/src/ScitillaComponent/Buffer.h | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/PowerEditor/src/ScitillaComponent/Buffer.cpp b/PowerEditor/src/ScitillaComponent/Buffer.cpp index 875bf973a..a5001fe85 100644 --- a/PowerEditor/src/ScitillaComponent/Buffer.cpp +++ b/PowerEditor/src/ScitillaComponent/Buffer.cpp @@ -38,13 +38,18 @@ FileManager * FileManager::_pSelf = new FileManager(); -const int blockSize = 128 * 1024 + 4; +static const int blockSize = 128 * 1024 + 4; // Ordre important!! Ne le changes pas! //SC_EOL_CRLF (0), SC_EOL_CR (1), or SC_EOL_LF (2). -const int CR = 0x0D; -const int LF = 0x0A; +static const int CR = 0x0D; +static const int LF = 0x0A; + + + + + Buffer::Buffer(FileManager * pManager, BufferID id, Document doc, DocFileStatus type, const TCHAR *fileName) //type must be either DOC_REGULAR or DOC_UNNAMED : _pManager(pManager), _id(id), _isDirty(false), _doc(doc), _isFileReadOnly(false), _isUserReadOnly(false), _recentTag(-1), _references(0), @@ -480,8 +485,9 @@ BufferID FileManager::loadFile(const TCHAR * filename, Document doc, int encodin Utf8_16_Read UnicodeConvertor; //declare here so we can get information after loading is done + char data[blockSize + 8]; // +8 for incomplete multibyte char formatType format; - bool res = loadFileData(doc, backupFileName?backupFileName:fullpath, &UnicodeConvertor, L_TEXT, encoding, &format); + bool res = loadFileData(doc, backupFileName?backupFileName:fullpath, data, &UnicodeConvertor, L_TEXT, encoding, &format); if (res) { Buffer * newBuf = new Buffer(this, _nextBufferID, doc, DOC_REGULAR, fullpath); @@ -560,14 +566,15 @@ bool FileManager::reloadBuffer(BufferID id) Utf8_16_Read UnicodeConvertor; buf->_canNotify = false; //disable notify during file load, we dont want dirty to be triggered int encoding = buf->getEncoding(); + char data[blockSize + 8]; // +8 for incomplete multibyte char formatType format; - bool res = loadFileData(doc, buf->getFullPathName(), &UnicodeConvertor, buf->getLangType(), encoding, &format); + bool res = loadFileData(doc, buf->getFullPathName(), data, &UnicodeConvertor, buf->getLangType(), encoding, &format); buf->_canNotify = true; if (res) { if (encoding == -1) { - if (UnicodeConvertor.getNewBuf()) + if (nullptr != UnicodeConvertor.getNewBuf()) { int format = getEOLFormatForm(UnicodeConvertor.getNewBuf()); buf->setFormat(format == -1?WIN_FORMAT:(formatType)format); @@ -1134,10 +1141,9 @@ int FileManager::detectCodepage(char* buf, size_t len) return codepage; } -bool FileManager::loadFileData(Document doc, const TCHAR * filename, Utf8_16_Read * UnicodeConvertor, LangType language, int & encoding, formatType *pFormat) +inline bool FileManager::loadFileData(Document doc, const TCHAR * filename, char* data, Utf8_16_Read * UnicodeConvertor, + LangType language, int & encoding, formatType *pFormat) { - const int blockSize = 128 * 1024; //128 kB - char data[blockSize+8]; FILE *fp = generic_fopen(filename, TEXT("rb")); if (!fp) return false; diff --git a/PowerEditor/src/ScitillaComponent/Buffer.h b/PowerEditor/src/ScitillaComponent/Buffer.h index 51c30cba4..d460f27db 100644 --- a/PowerEditor/src/ScitillaComponent/Buffer.h +++ b/PowerEditor/src/ScitillaComponent/Buffer.h @@ -120,7 +120,7 @@ private: size_t _nrBufs; int detectCodepage(char* buf, size_t len); - bool loadFileData(Document doc, const TCHAR * filename, Utf8_16_Read * UnicodeConvertor, LangType language, int & encoding, formatType *pFormat = NULL); + bool loadFileData(Document doc, const TCHAR * filename, char* buffer, Utf8_16_Read * UnicodeConvertor, LangType language, int & encoding, formatType *pFormat = NULL); }; #define MainFileManager FileManager::getInstance()