diff options
Diffstat (limited to 'modules/fbx/fbx_parser/FBXBinaryTokenizer.cpp')
-rw-r--r-- | modules/fbx/fbx_parser/FBXBinaryTokenizer.cpp | 87 |
1 files changed, 31 insertions, 56 deletions
diff --git a/modules/fbx/fbx_parser/FBXBinaryTokenizer.cpp b/modules/fbx/fbx_parser/FBXBinaryTokenizer.cpp index 1d2b7765c5..d6abcbb00a 100644 --- a/modules/fbx/fbx_parser/FBXBinaryTokenizer.cpp +++ b/modules/fbx/fbx_parser/FBXBinaryTokenizer.cpp @@ -82,46 +82,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <stdint.h> namespace FBXDocParser { -//enum Flag -//{ -// e_unknown_0 = 1 << 0, -// e_unknown_1 = 1 << 1, -// e_unknown_2 = 1 << 2, -// e_unknown_3 = 1 << 3, -// e_unknown_4 = 1 << 4, -// e_unknown_5 = 1 << 5, -// e_unknown_6 = 1 << 6, -// e_unknown_7 = 1 << 7, -// e_unknown_8 = 1 << 8, -// e_unknown_9 = 1 << 9, -// e_unknown_10 = 1 << 10, -// e_unknown_11 = 1 << 11, -// e_unknown_12 = 1 << 12, -// e_unknown_13 = 1 << 13, -// e_unknown_14 = 1 << 14, -// e_unknown_15 = 1 << 15, -// e_unknown_16 = 1 << 16, -// e_unknown_17 = 1 << 17, -// e_unknown_18 = 1 << 18, -// e_unknown_19 = 1 << 19, -// e_unknown_20 = 1 << 20, -// e_unknown_21 = 1 << 21, -// e_unknown_22 = 1 << 22, -// e_unknown_23 = 1 << 23, -// e_flag_field_size_64_bit = 1 << 24, // Not sure what is -// e_unknown_25 = 1 << 25, -// e_unknown_26 = 1 << 26, -// e_unknown_27 = 1 << 27, -// e_unknown_28 = 1 << 28, -// e_unknown_29 = 1 << 29, -// e_unknown_30 = 1 << 30, -// e_unknown_31 = 1 << 31 -//}; -// -//bool check_flag(uint32_t flags, Flag to_check) -//{ -// return (flags & to_check) != 0; -//} // ------------------------------------------------------------------------------------------------ Token::Token(const char *sbegin, const char *send, TokenType type, size_t offset) : sbegin(sbegin), @@ -130,6 +90,7 @@ Token::Token(const char *sbegin, const char *send, TokenType type, size_t offset line(offset), column(BINARY_MARKER) { #ifdef DEBUG_ENABLED + // contents is bad.. :/ contents = std::string(sbegin, static_cast<size_t>(send - sbegin)); #endif // calc length @@ -232,9 +193,11 @@ unsigned int ReadString(const char *&sbegin_out, const char *&send_out, const ch } // ------------------------------------------------------------------------------------------------ -void ReadData(const char *&sbegin_out, const char *&send_out, const char *input, const char *&cursor, const char *end) { +void ReadData(const char *&sbegin_out, const char *&send_out, const char *input, const char *&cursor, const char *end, bool &corrupt) { if (Offset(cursor, end) < 1) { TokenizeError("cannot ReadData, out of bounds reading length", input, cursor); + corrupt = true; + return; } const char type = *cursor; @@ -328,9 +291,7 @@ void ReadData(const char *&sbegin_out, const char *&send_out, const char *input, } cursor += comp_len; break; - } - - // string + } // string case 'S': { const char *sb, *se; // 0 characters can legally happen in such strings @@ -338,11 +299,15 @@ void ReadData(const char *&sbegin_out, const char *&send_out, const char *input, break; } default: + corrupt = true; // must exit TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1), input, cursor); + return; } if (cursor > end) { + corrupt = true; // must exit TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1), input, cursor); + return; } // the type code is contained in the returned range @@ -350,7 +315,7 @@ void ReadData(const char *&sbegin_out, const char *&send_out, const char *input, } // ------------------------------------------------------------------------------------------------ -bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, const char *end, bool const is64bits) { +bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, const char *end, bool const is64bits, bool &corrupt) { // the first word contains the offset at which this block ends const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); @@ -364,8 +329,12 @@ bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, if (end_offset > Offset(input, end)) { TokenizeError("block offset is out of range", input, cursor); + corrupt = true; + return false; } else if (end_offset < Offset(input, cursor)) { TokenizeError("block offset is negative out of range", input, cursor); + corrupt = true; + return false; } // the second data word contains the number of properties in the scope @@ -375,7 +344,7 @@ bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); // now comes the name of the scope/key - const char *sbeg, *send; + const char *sbeg = nullptr, *send = nullptr; ReadString(sbeg, send, input, cursor, end); output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor))); @@ -383,7 +352,10 @@ bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, // now come the individual properties const char *begin_cursor = cursor; for (unsigned int i = 0; i < prop_count; ++i) { - ReadData(sbeg, send, input, cursor, begin_cursor + prop_length); + ReadData(sbeg, send, input, cursor, begin_cursor + prop_length, corrupt); + if (corrupt) { + return false; + } output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor))); @@ -394,6 +366,8 @@ bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, if (Offset(begin_cursor, cursor) != prop_length) { TokenizeError("property length not reached, something is wrong", input, cursor); + corrupt = true; + return false; } // at the end of each nested block, there is a NUL record to indicate @@ -410,13 +384,18 @@ bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, // XXX this is vulnerable to stack overflowing .. while (Offset(input, cursor) < end_offset - sentinel_block_length) { - ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits); + ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits, corrupt); + if (corrupt) { + return false; + } } output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor))); for (unsigned int i = 0; i < sentinel_block_length; ++i) { if (cursor[i] != '\0') { TokenizeError("failed to read nested block sentinel, expected all bytes to be 0", input, cursor); + corrupt = true; + return false; } } cursor += sentinel_block_length; @@ -424,6 +403,8 @@ bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, if (Offset(input, cursor) != end_offset) { TokenizeError("scope length not reached, something is wrong", input, cursor); + corrupt = true; + return false; } return true; @@ -432,17 +413,11 @@ bool ReadScope(TokenList &output_tokens, const char *input, const char *&cursor, // ------------------------------------------------------------------------------------------------ // TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent -void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length) { +void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, bool &corrupt) { if (length < 0x1b) { //TokenizeError("file is too short",0); } - //uint32_t offset = 0x15; - /* const char* cursor = input + 0x15; - const uint32_t flags = ReadWord(input, cursor, input + length); - const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused - const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused*/ - if (strncmp(input, "Kaydara FBX Binary", 18)) { TokenizeError("magic bytes not found", 0); } @@ -459,7 +434,7 @@ void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length) const bool is64bits = version >= 7500; const char *end = input + length; while (cursor < end) { - if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) { + if (!ReadScope(output_tokens, input, cursor, input + length, is64bits, corrupt)) { break; } } |