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`).
This commit is contained in:
milipili 2015-05-30 20:32:33 +02:00 committed by Damien GERARD
parent 17e8ca3c15
commit 6adc3b35fc
2 changed files with 16 additions and 10 deletions

View File

@ -38,13 +38,18 @@
FileManager * FileManager::_pSelf = new FileManager(); FileManager * FileManager::_pSelf = new FileManager();
const int blockSize = 128 * 1024 + 4; static const int blockSize = 128 * 1024 + 4;
// Ordre important!! Ne le changes pas! // Ordre important!! Ne le changes pas!
//SC_EOL_CRLF (0), SC_EOL_CR (1), or SC_EOL_LF (2). //SC_EOL_CRLF (0), SC_EOL_CR (1), or SC_EOL_LF (2).
const int CR = 0x0D; static const int CR = 0x0D;
const int LF = 0x0A; 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 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), : _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 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; 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) if (res)
{ {
Buffer * newBuf = new Buffer(this, _nextBufferID, doc, DOC_REGULAR, fullpath); Buffer * newBuf = new Buffer(this, _nextBufferID, doc, DOC_REGULAR, fullpath);
@ -560,14 +566,15 @@ bool FileManager::reloadBuffer(BufferID id)
Utf8_16_Read UnicodeConvertor; Utf8_16_Read UnicodeConvertor;
buf->_canNotify = false; //disable notify during file load, we dont want dirty to be triggered buf->_canNotify = false; //disable notify during file load, we dont want dirty to be triggered
int encoding = buf->getEncoding(); int encoding = buf->getEncoding();
char data[blockSize + 8]; // +8 for incomplete multibyte char
formatType format; 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; buf->_canNotify = true;
if (res) if (res)
{ {
if (encoding == -1) if (encoding == -1)
{ {
if (UnicodeConvertor.getNewBuf()) if (nullptr != UnicodeConvertor.getNewBuf())
{ {
int format = getEOLFormatForm(UnicodeConvertor.getNewBuf()); int format = getEOLFormatForm(UnicodeConvertor.getNewBuf());
buf->setFormat(format == -1?WIN_FORMAT:(formatType)format); buf->setFormat(format == -1?WIN_FORMAT:(formatType)format);
@ -1134,10 +1141,9 @@ int FileManager::detectCodepage(char* buf, size_t len)
return codepage; 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")); FILE *fp = generic_fopen(filename, TEXT("rb"));
if (!fp) if (!fp)
return false; return false;

View File

@ -120,7 +120,7 @@ private:
size_t _nrBufs; size_t _nrBufs;
int detectCodepage(char* buf, size_t len); 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() #define MainFileManager FileManager::getInstance()