COB: fix validation for ascii header (#6376)
* COB: fix validation for ascii header
This commit is contained in:
@@ -62,6 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <memory>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
using namespace Assimp::COB;
|
||||
using namespace Assimp::Formatter;
|
||||
|
||||
@@ -109,10 +110,29 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/*static*/ AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) {
|
||||
AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) {
|
||||
throw DeadlyImportError("COB: ", msg);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static bool isValidASCIIHeader(const char *head) {
|
||||
ai_assert(head != nullptr);
|
||||
|
||||
if (strncmp(head, "Caligari ", 9) != 0) {
|
||||
COBImporter::ThrowException("Could not found magic id: `Caligari`");
|
||||
}
|
||||
|
||||
if (strncmp(&head[9], "V00.", 4) != 0) {
|
||||
COBImporter::ThrowException("Could not found Version tag: `V00.`");
|
||||
}
|
||||
ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
|
||||
if (head[16] != 'L') {
|
||||
COBImporter::ThrowException("File is big-endian, which is not supported");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
|
||||
@@ -126,19 +146,15 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file));
|
||||
|
||||
// check header
|
||||
char head[32];
|
||||
stream->CopyAndAdvance(head, 32);
|
||||
if (strncmp(head, "Caligari ", 9) != 0) {
|
||||
ThrowException("Could not found magic id: `Caligari`");
|
||||
}
|
||||
|
||||
ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
|
||||
if (head[16] != 'L') {
|
||||
ThrowException("File is big-endian, which is not supported");
|
||||
}
|
||||
static constexpr size_t HeaderSize = 32u;
|
||||
char head[HeaderSize] = {};
|
||||
stream->CopyAndAdvance(head, HeaderSize);
|
||||
|
||||
// load data into intermediate structures
|
||||
if (head[15] == 'A') {
|
||||
if (!isValidASCIIHeader(head)) {
|
||||
ThrowException("Invalid ASCII file header");
|
||||
}
|
||||
ReadAsciiFile(scene, stream.get());
|
||||
} else {
|
||||
ReadBinaryFile(scene, stream.get());
|
||||
@@ -1170,6 +1186,6 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
|
||||
ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_COB_IMPORTER
|
||||
|
||||
@@ -81,6 +81,10 @@ public:
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
|
||||
bool checkSig) const override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Prepend 'COB: ' and throw msg.*/
|
||||
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
protected:
|
||||
// --------------------
|
||||
const aiImporterDesc *GetInfo() const override;
|
||||
@@ -93,10 +97,6 @@ protected:
|
||||
IOSystem *pIOHandler) override;
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
/** Prepend 'COB: ' and throw msg.*/
|
||||
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Read from an ascii scene/object file
|
||||
* @param out Receives output data.
|
||||
@@ -148,4 +148,5 @@ private:
|
||||
}; // !class COBImporter
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_UNREALIMPORTER_H_INC
|
||||
|
||||
@@ -65,7 +65,8 @@ struct VertexIndex {
|
||||
/** COB Face data structure */
|
||||
struct Face {
|
||||
// intentionally uninitialized
|
||||
unsigned int material, flags;
|
||||
unsigned int material;
|
||||
unsigned int flags;
|
||||
std::vector<VertexIndex> indices;
|
||||
};
|
||||
|
||||
@@ -74,41 +75,43 @@ struct Face {
|
||||
constexpr unsigned int NO_SIZE = UINT_MAX;
|
||||
|
||||
struct ChunkInfo {
|
||||
ChunkInfo ()
|
||||
: id (0)
|
||||
, parent_id (0)
|
||||
, version (0)
|
||||
, size (NO_SIZE)
|
||||
{}
|
||||
ChunkInfo() = default;
|
||||
virtual ~ChunkInfo() = default;
|
||||
|
||||
// Id of this chunk, unique within file
|
||||
unsigned int id;
|
||||
unsigned int id{ 0 };
|
||||
|
||||
// and the corresponding parent
|
||||
unsigned int parent_id;
|
||||
unsigned int parent_id{ 0 };
|
||||
|
||||
// version. v1.23 becomes 123
|
||||
unsigned int version;
|
||||
unsigned int version{ 0 };
|
||||
|
||||
// chunk size in bytes, only relevant for binary files
|
||||
// NO_SIZE is also valid.
|
||||
unsigned int size;
|
||||
unsigned int size{NO_SIZE};
|
||||
};
|
||||
|
||||
// ------------------
|
||||
/** A node in the scenegraph */
|
||||
struct Node : ChunkInfo {
|
||||
enum Type {
|
||||
TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
|
||||
TYPE_INVALID = -1,
|
||||
TYPE_MESH = 0,
|
||||
TYPE_GROUP,
|
||||
TYPE_LIGHT,
|
||||
TYPE_CAMERA,
|
||||
TYPE_BONE,
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
virtual ~Node() = default;
|
||||
~Node() override = default;
|
||||
Node(Type type) : type(type), unit_scale(1.f){}
|
||||
|
||||
Type type;
|
||||
|
||||
// used during resolving
|
||||
typedef std::deque<const Node*> ChildList;
|
||||
using ChildList = std::deque<const Node*> ;
|
||||
mutable ChildList temp_children;
|
||||
|
||||
// unique name
|
||||
@@ -123,8 +126,7 @@ struct Node : ChunkInfo {
|
||||
|
||||
// ------------------
|
||||
/** COB Mesh data structure */
|
||||
struct Mesh final : Node
|
||||
{
|
||||
struct Mesh final : Node {
|
||||
using ChunkInfo::operator=;
|
||||
enum DrawFlags {
|
||||
SOLID = 0x1,
|
||||
@@ -159,36 +161,49 @@ struct Mesh final : Node
|
||||
/** COB Group data structure */
|
||||
struct Group final : Node {
|
||||
using ChunkInfo::operator=;
|
||||
Group() : Node(TYPE_GROUP) {}
|
||||
|
||||
Group() : Node(TYPE_GROUP) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------
|
||||
/** COB Bone data structure */
|
||||
struct Bone final : Node {
|
||||
using ChunkInfo::operator=;
|
||||
Bone() : Node(TYPE_BONE) {}
|
||||
|
||||
Bone() : Node(TYPE_BONE) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------
|
||||
/** COB Light data structure */
|
||||
struct Light final : Node {
|
||||
enum LightType {
|
||||
SPOT,LOCAL,INFINITE
|
||||
SPOT,
|
||||
LOCAL,
|
||||
INFINITE
|
||||
};
|
||||
|
||||
using ChunkInfo::operator=;
|
||||
Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
|
||||
|
||||
Light() : Node(TYPE_LIGHT), ltype() {
|
||||
// empty
|
||||
}
|
||||
|
||||
aiColor3D color;
|
||||
float angle,inner_angle;
|
||||
float angle{ 0.0f };
|
||||
float inner_angle{ 0.0f };
|
||||
|
||||
LightType ltype;
|
||||
LightType ltype{SPOT};
|
||||
};
|
||||
|
||||
// ------------------
|
||||
/** COB Camera data structure */
|
||||
struct Camera final : Node {
|
||||
using ChunkInfo::operator=;
|
||||
|
||||
Camera() : Node(TYPE_CAMERA) {
|
||||
// empty
|
||||
}
|
||||
@@ -205,47 +220,48 @@ struct Texture {
|
||||
/** COB Material data structure */
|
||||
struct Material : ChunkInfo {
|
||||
using ChunkInfo::operator=;
|
||||
|
||||
enum Shader {
|
||||
FLAT,PHONG,METAL
|
||||
FLAT,
|
||||
PHONG,
|
||||
METAL
|
||||
};
|
||||
|
||||
enum AutoFacet {
|
||||
FACETED,AUTOFACETED,SMOOTH
|
||||
FACETED,
|
||||
AUTOFACETED,
|
||||
SMOOTH
|
||||
};
|
||||
|
||||
Material() : alpha(),exp(),ior(),ka(),ks(1.f),
|
||||
matnum(UINT_MAX),
|
||||
shader(FLAT),autofacet(FACETED),
|
||||
autofacet_angle()
|
||||
{}
|
||||
Material() : shader(FLAT) {
|
||||
// empty
|
||||
}
|
||||
|
||||
std::string type;
|
||||
|
||||
aiColor3D rgb;
|
||||
float alpha, exp, ior,ka,ks;
|
||||
|
||||
unsigned int matnum;
|
||||
float alpha{ 0.0f };
|
||||
float exp{ 0.0f };
|
||||
float ior{ 0.0f };
|
||||
float ka{ 0.0f };
|
||||
float ks{ 1.0f };
|
||||
unsigned int matnum{ UINT_MAX };
|
||||
Shader shader;
|
||||
|
||||
AutoFacet autofacet;
|
||||
float autofacet_angle;
|
||||
|
||||
AutoFacet autofacet{FACETED};
|
||||
float autofacet_angle{ 0.0f };
|
||||
std::shared_ptr<Texture> tex_env,tex_bump,tex_color;
|
||||
};
|
||||
|
||||
// ------------------
|
||||
/** Embedded bitmap, for instance for the thumbnail image */
|
||||
struct Bitmap : ChunkInfo {
|
||||
Bitmap() : orig_size() {
|
||||
// empty
|
||||
}
|
||||
Bitmap() = default;
|
||||
|
||||
struct BitmapHeader {
|
||||
// empty
|
||||
};
|
||||
|
||||
BitmapHeader head;
|
||||
size_t orig_size;
|
||||
size_t orig_size{ 0u };
|
||||
std::vector<char> buff_zipped;
|
||||
};
|
||||
|
||||
@@ -264,4 +280,4 @@ struct Scene {
|
||||
|
||||
} // end Assimp::COB
|
||||
|
||||
#endif
|
||||
#endif // INCLUDED_AI_COB_SCENE_H
|
||||
|
||||
@@ -59,14 +59,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
namespace Assimp {
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
/** Wrapper class around IOStream to allow for consistent reading of binary data in both
|
||||
* little and big endian format. Don't attempt to instance the template directly. Use
|
||||
* StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a
|
||||
* BE stream. The class expects that the endianness of any input data is known at
|
||||
* compile-time, which should usually be true (#BaseImporter::ConvertToUTF8 implements
|
||||
* runtime endianness conversions for text files).
|
||||
/**
|
||||
* @brief Wrapper class around IOStream to allow for consistent reading of binary data in both
|
||||
* little and big endian format.
|
||||
*
|
||||
* XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/
|
||||
* Don't attempt to instance the template directly. Use StreamReaderLE to read from a
|
||||
* little-endian stream and StreamReaderBE to read from a BE stream. The class expects that
|
||||
* the endianness of any input data is known at compile-time, which should usually be true
|
||||
* (#BaseImporter::ConvertToUTF8 implements runtime endianness conversions for text files).
|
||||
*
|
||||
* XXX switch from unsigned int for size types to size_t? or ptrdiff_t?
|
||||
*/
|
||||
// --------------------------------------------------------------------------------------------
|
||||
template <bool SwapEndianness = false, bool RuntimeSwitch = false>
|
||||
class StreamReader {
|
||||
|
||||
@@ -95,3 +95,10 @@ TEST(utCOBImporter, importSpider66) {
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/COB/spider_6_6.cob", aiProcess_ValidateDataStructure);
|
||||
ASSERT_NE(nullptr, scene);
|
||||
}
|
||||
|
||||
TEST(utCOBImporter, importInvalidHeader) {
|
||||
Assimp::Importer importer;
|
||||
constexpr char Header[] = "Caligari ??LZSCALEb";
|
||||
const aiScene *scene = importer.ReadFileFromMemory(Header, sizeof(Header), aiProcess_ValidateDataStructure);
|
||||
ASSERT_EQ(nullptr, scene);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user