From: James Turner Date: Thu, 17 Oct 2013 19:13:36 +0000 (+0100) Subject: Avoid a divide-by-zero on malformed BTG files. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=8b0c246a7b6fc31fc7fec715ec4e6f6785314889;p=simgear.git Avoid a divide-by-zero on malformed BTG files. Encountered while testing v850 airports; some airports generate materials with no tris, and hence no indices. This causes a divide-by-zero when computing the index stride. Detect this, and convert the BTG reader to throw exceptions in error conditions, and to catch this and report the appropriate result code. --- diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index 704d9e3a..69cdd477 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -43,6 +43,7 @@ #include #include #include +#include #include "lowlevel.hxx" #include "sg_binobj.hxx" @@ -319,15 +320,18 @@ void SGBinObject::read_object( gzFile fp, } if ( sgReadError() ) { - cout << "We detected an error reading object properties" << endl; - return; + throw sg_exception("Error reading object properties"); + } + + size_t indexCount = std::bitset<32>(idx_mask).count(); + if (indexCount == 0) { + throw sg_exception("object index mask has no bits set"); } for ( j = 0; j < nelements; ++j ) { sgReadUInt( fp, &nbytes ); if ( sgReadError() ) { - cout << "We detected an error reading element size for :" << j << endl; - return; + throw sg_exception("Error reading element size"); } buf.resize( nbytes ); @@ -335,8 +339,7 @@ void SGBinObject::read_object( gzFile fp, sgReadBytes( fp, nbytes, ptr ); if ( sgReadError() ) { - cout << "We detected an error reading object element:" << j << "bytes="<< nbytes << endl; - return; + throw sg_exception("Error reading element bytes"); } int_list vs; @@ -405,7 +408,7 @@ bool SGBinObject::read_bin( const string& file ) { SG_LOG( SG_EVENT, SG_ALERT, "ERROR: opening " << file << " or " << filegz << " for reading!"); - return false; + throw sg_io_exception("Error opening for reading (and .gz)", sg_location(file)); } } @@ -423,9 +426,7 @@ bool SGBinObject::read_bin( const string& file ) { } else { // close the file before we return gzclose(fp); - SG_LOG( SG_EVENT, SG_ALERT, - "ERROR: " << file << "has bad header"); - return false; + throw sg_io_exception("Bad BTG magic/version", sg_location(file)); } // read creation time @@ -462,8 +463,7 @@ bool SGBinObject::read_bin( const string& file ) { //cout << "Total objects to read = " << nobjects << endl; if ( sgReadError() ) { - cout << "Error while reading header of file " << file << "(.gz)" << endl; - return false; + throw sg_io_exception("Error reading BTG file header", sg_location(file)); } // read in objects @@ -613,19 +613,13 @@ bool SGBinObject::read_bin( const string& file ) { } if ( sgReadError() ) { - cout << "Error while reading object:" << i << " in file " << file << "(.gz)" << endl; - return false; + throw sg_io_exception("Error while reading object", sg_location(file, i)); } } // close the file gzclose(fp); - if ( sgReadError() ) { - cout << "Error while reading file " << file << "(.gz)" << endl; - return false; - } - return true; } @@ -665,7 +659,7 @@ void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts, if (verts.empty()) { return; } - + unsigned int start = 0, end = 1; string m; int_list emptyList; @@ -688,6 +682,13 @@ void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts, if ( !normals.empty() && !normals.front().empty()) idx_mask |= SG_IDX_NORMALS; if ( !colors.empty() && !colors.front().empty()) idx_mask |= SG_IDX_COLORS; if ( !texCoords.empty() && !texCoords.front().empty()) idx_mask |= SG_IDX_TEXCOORDS; + + if (idx_mask == 0) { + SG_LOG(SG_IO, SG_ALERT, "SGBinObject::write_objects: object with material:" + << m << "has no indices set"); + } + + sgWriteChar( fp, (char)SG_INDEX_TYPES ); // property sgWriteUInt( fp, 1 ); // nbytes sgWriteChar( fp, idx_mask ); diff --git a/simgear/scene/tgdb/SGReaderWriterBTG.cxx b/simgear/scene/tgdb/SGReaderWriterBTG.cxx index ba53ee32..fa0a2175 100644 --- a/simgear/scene/tgdb/SGReaderWriterBTG.cxx +++ b/simgear/scene/tgdb/SGReaderWriterBTG.cxx @@ -24,6 +24,7 @@ #include #include +#include #include "SGReaderWriterBTG.hxx" #include "obj.hxx" @@ -60,10 +61,17 @@ SGReaderWriterBTG::readNode(const std::string& fileName, { const SGReaderWriterOptions* sgOptions; sgOptions = dynamic_cast(options); - osg::Node* result = SGLoadBTG(fileName, sgOptions); - if (!result) - return ReadResult::FILE_NOT_HANDLED; - + osg::Node* result = NULL; + try { + result = SGLoadBTG(fileName, sgOptions); + if (!result) + return ReadResult::FILE_NOT_HANDLED; + } catch (sg_exception& e) { + SG_LOG(SG_IO, SG_WARN, "error reading:" << fileName << ":" << + e.getFormattedMessage()); + return ReadResult::ERROR_IN_READING_FILE; + } + return result; }