Merge branch 'issue1060'

heavy-resources
Nicolas Hake 2014-03-25 18:30:53 +01:00
commit e230c90e0b
5 changed files with 78 additions and 17 deletions

View File

@ -0,0 +1,2 @@
[Material]
Name=Material

View File

@ -0,0 +1 @@
1=Material

View File

@ -0,0 +1,5 @@
[Head]
Title=Test case for #1060
[Definitions]
LocalOnly=1

View File

@ -0,0 +1 @@
US:#1060: Incorrectly formatted TexMap causes nullpointer deref

View File

@ -29,6 +29,9 @@
#include <C4Landscape.h>
#include <C4Log.h>
#include <ctype.h>
#include <algorithm>
C4Texture::C4Texture()
{
Name[0]=0;
@ -207,30 +210,79 @@ bool C4TextureMap::LoadFlags(C4Group &hGroup, const char *szEntryName, bool *pOv
int32_t C4TextureMap::LoadMap(C4Group &hGroup, const char *szEntryName, bool *pOverloadMaterials, bool *pOverloadTextures)
{
static re::regex line_terminator("\r?\n", static_cast<re::regex::flag_type>(re::regex_constants::optimize | re::regex_constants::ECMAScript));
char *bpMap;
char szLine[100+1];
int32_t cnt, iIndex, iTextures = 0;
size_t map_size;
int32_t iTextures = 0;
// Load text file into memory
if (!hGroup.LoadEntry(szEntryName,&bpMap,NULL,1)) return 0;
// Scan text buffer lines
for (cnt=0; SCopySegment(bpMap,cnt,szLine,0x0A,100); cnt++)
if ( (szLine[0]!='#') && (SCharCount('=',szLine)==1) )
if (!hGroup.LoadEntry(szEntryName,&bpMap,&map_size,1)) return 0;
char *begin = bpMap;
char *end = begin + map_size;
size_t line = 1; // Counter for error messages
for (auto it = re::cregex_token_iterator(begin, end, line_terminator, -1); it != re::cregex_token_iterator(); ++it, ++line)
{
if (it->compare("OverloadMaterials") == 0)
{
SReplaceChar(szLine,0x0D,0x00);
if (Inside<int32_t>( iIndex = strtol(szLine,NULL,10), 0, C4M_MaxTexIndex-1 ))
{
const char *szMapping = szLine+SCharPos('=',szLine)+1;
StdStrBuf Material, Texture;
Material.CopyUntil(szMapping, '-'); Texture.Copy(SSearch(szMapping, "-"));
if (AddEntry(iIndex, Material.getData(), Texture.getData()))
iTextures++;
}
fOverloadMaterials = true;
if (pOverloadMaterials)
*pOverloadMaterials = true;
}
else if (it->compare("OverloadTextures") == 0)
{
fOverloadTextures = true;
if (pOverloadTextures)
*pOverloadTextures = true;
}
else if (it->length() == 0 || it->first[0] == '#' || std::all_of(it->first, it->second, &isspace))
{
// Skip empty lines, comments, and all-whitespace lines
continue;
}
else
{
if (SEqual2(szLine, "OverloadMaterials")) { fOverloadMaterials = true; if (pOverloadMaterials) *pOverloadMaterials = true; }
if (SEqual2(szLine, "OverloadTextures")) { fOverloadTextures = true; if (pOverloadTextures) *pOverloadTextures = true; }
// This must be a texmap entry now
std::string value;
// Read index
unsigned long index;
try
{
size_t separator;
index = std::stoul(it->str(), &separator, 10);
if (index >= C4M_MaxTexIndex)
throw std::out_of_range("Texture index out of range");
value.assign(it->first + separator + 1, it->second);
}
catch (std::invalid_argument &)
{
DebugLogF("TexMap line %u: Texture index is not numeric", static_cast<unsigned>(line));
continue;
}
catch (std::out_of_range &)
{
DebugLogF("TexMap line %u: Texture index is out of range", static_cast<unsigned>(line));
continue;
}
// Split material/texture combination
std::string::const_iterator separator = std::find(value.cbegin(), value.cend(), '-');
if (separator == value.cend())
{
DebugLogF("TexMap line %u: Texture name \"%s\" is invalid (missing \"-\")", static_cast<unsigned>(line), value.c_str());
continue;
}
std::string material(value.cbegin(), separator);
std::string texture(separator + 1, value.cend());
if (AddEntry(index, material.c_str(), texture.c_str()))
++iTextures;
}
}
// Delete buffer, return entry count
delete [] bpMap;
fEntriesAdded=false;