ExcelFormat是C++读取xls文件的库,来自:
http://www.codeproject.com/Articles/42504/ExcelFormat-Library
https://github.com/metamaker/ExcelFormat-BiiExample
使用过程中发现了一个问题,提示vector访问超过范围。经过调试问题在BasicExcel.cpp文件中,改正的代码如下:
只增加了一行代码,strings_[i].Read1(&*(data_.begin())+npos);
分析过程:
在调试过程中发现,phonetic_没有读取实际应该是16,但是他是0。因为他没有读取unicode_、richtext_、phonetic_,因此出现这个错误。他将phonetic_标志当成字符串内容读取了,下次读取的时候字符串长度已经不是协议中得了多次以后造成内存访问超过范围错误。
ULONG Workbook::SharedStringTable::Read(const char* data)
{
Record::Read(data);
LittleEndian::Read(data_, stringsTotal_, 0, 4);
LittleEndian::Read(data_, uniqueStringsTotal_, 4, 4);
strings_.clear();
strings_.resize(uniqueStringsTotal_);
ULONG npos = 8;
if (continueIndices_.empty()) {
for(ULONG i=0; i<uniqueStringsTotal_; ++i)
npos += strings_[i].Read(&*(data_.begin())+npos);
} else {
// Require special handling since CONTINUE records are present
ULONG maxContinue = (ULONG) continueIndices_.size();
for(ULONG i=0, c=0; i<uniqueStringsTotal_; ++i) {
char unicode;
ULONG stringSize;
LittleEndian::Read(data_, stringSize, npos, 2);
LittleEndian::Read(data_, unicode, npos+2, 1);
int multiplier = unicode & 1 ? 2 : 1;
if (c >= maxContinue || npos+stringSize*multiplier+3 <= continueIndices_[c]) {
// String to be read is not split into two records
npos += strings_[i].Read(&*(data_.begin())+npos);
} else {
//2019-03-01 by cch 解决标记未读取的错误
strings_[i].Read1(&*(data_.begin())+npos);
// String to be read is split into two or more records
int bytesRead = 2;// Start from unicode field
int size = continueIndices_[c] - npos - 1 - bytesRead;
++c;
if (size > 0) {
size /= multiplier; // Number of characters available for string in current record.
bytesRead += strings_[i].ContinueRead(&*(data_.begin())+npos+bytesRead, size);
stringSize -= size;
size = 0;
}
while(c<maxContinue && npos+stringSize+1>continueIndices_[c]) {
ULONG dataSize = (continueIndices_[c] - continueIndices_[c-1] - 1) / multiplier;
bytesRead += strings_[i].ContinueRead(&*(data_.begin())+npos+bytesRead, dataSize);
stringSize -= dataSize + 1;
++c;
}
if (stringSize > 0)
bytesRead += strings_[i].ContinueRead(&*(data_.begin())+npos+bytesRead, stringSize);
npos += bytesRead;
}
}
}
return npos + 4*(npos/8224 + 1);
}
void LargeString::Read1(const char* data)
{
//short stringSize;
//LittleEndian::Read(data, stringSize, 0, 2);
LittleEndian::Read(data, unicode_, 2, 1);
ULONG npos = 3;
if (unicode_ & 8) {
LittleEndian::Read(data, richtext_, npos, 2);
npos += 2;
}
if (unicode_ & 4)
LittleEndian::Read(data, phonetic_, npos, 4);
name_.clear();
wname_.clear();
}