From 028e4323e1b7ebfc3b21b07209188f301a6cd6cc Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sat, 5 Dec 2015 19:37:26 -0800 Subject: [PATCH] Fix crash when trying to read/write a string with 0 length --- include/Athena/IStreamReader.hpp | 19 +++++ include/Athena/IStreamWriter.hpp | 127 ++++++++++++++++++------------- 2 files changed, 92 insertions(+), 54 deletions(-) diff --git a/include/Athena/IStreamReader.hpp b/include/Athena/IStreamReader.hpp index 9886d20..1540f64 100644 --- a/include/Athena/IStreamReader.hpp +++ b/include/Athena/IStreamReader.hpp @@ -883,6 +883,9 @@ public: */ inline std::string readWStringAsString(atInt32 fixedLen = -1) { + if (fixedLen == 0) + return std::string(); + std::string retval; atUint16 chr = readUint16(); @@ -921,6 +924,9 @@ public: */ inline std::string readWStringAsStringLittle(atInt32 fixedLen = -1) { + if (fixedLen == 0) + return std::string(); + std::string retval; atUint16 chr = readUint16Little(); @@ -959,6 +965,9 @@ public: */ inline std::string readWStringAsStringBig(atInt32 fixedLen = -1) { + if (fixedLen == 0) + return std::string(); + std::string retval; atUint16 chr = readUint16Big(); @@ -996,6 +1005,8 @@ public: */ inline std::string readString(atInt32 fixedLen = -1) { + if (fixedLen == 0) + return std::string(); std::string ret; atUint8 chr = readByte(); @@ -1026,6 +1037,9 @@ public: */ inline std::wstring readWString(atInt32 fixedLen = -1) { + if (fixedLen == 0) + return std::wstring(); + std::wstring ret; atUint16 chr = readUint16(); @@ -1057,6 +1071,9 @@ public: */ inline std::wstring readWStringLittle(atInt32 fixedLen = -1) { + if (fixedLen == 0) + return std::wstring(); + std::wstring ret; atUint16 chr = readUint16Little(); @@ -1088,6 +1105,8 @@ public: */ inline std::wstring readWStringBig(atInt32 fixedLen = -1) { + if (fixedLen == 0) + return std::wstring(); std::wstring ret; atUint16 chr = readUint16Big(); diff --git a/include/Athena/IStreamWriter.hpp b/include/Athena/IStreamWriter.hpp index 2d02ed3..0db42f3 100644 --- a/include/Athena/IStreamWriter.hpp +++ b/include/Athena/IStreamWriter.hpp @@ -712,50 +712,52 @@ public: */ inline void writeStringAsWString(const std::string& str, atInt32 fixedLen = -1) { - std::string tmpStr = "\xEF\xBB\xBF" + str; - const utf8proc_uint8_t* buf = reinterpret_cast(tmpStr.c_str()); - if (fixedLen < 0) - { - while (*buf) - { - utf8proc_int32_t wc; - utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); - if (len < 0) - { - atWarning("invalid UTF-8 character while decoding"); - return; - } - buf += len; - if (wc != 0xFEFF) - writeUint16(atUint16(wc)); - } - writeUint16(0); - } - else - { - for (atInt32 i=0 ; i(tmpStr.c_str()); + if (fixedLen < 0) + { + while (*buf) + { + utf8proc_int32_t wc; + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) + { + atWarning("invalid UTF-8 character while decoding"); + return; + } + buf += len; + if (wc != 0xFEFF) + writeUint16(atUint16(wc)); + } + writeUint16(0); + } + else + { + for (atInt32 i=0 ; i(tmpStr.c_str()); if (fixedLen < 0) @@ -824,6 +828,9 @@ public: */ inline void writeStringAsWStringBig(const std::string& str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + std::string tmpStr = "\xEF\xBB\xBF" + str; const utf8proc_uint8_t* buf = reinterpret_cast(tmpStr.c_str()); if (fixedLen < 0) @@ -877,6 +884,9 @@ public: */ inline void writeString(const std::string& str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + if (fixedLen < 0) { for (atUint8 c : str) @@ -913,6 +923,9 @@ public: */ inline void writeWString(const std::wstring& str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + if (fixedLen < 0) { for (atUint16 c : str) @@ -949,6 +962,9 @@ public: */ inline void writeWStringLittle(const std::wstring& str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + if (fixedLen < 0) { for (atUint16 c : str) @@ -985,6 +1001,9 @@ public: */ inline void writeWStringBig(const std::wstring& str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + if (fixedLen < 0) { for (atUint16 c : str) @@ -1025,9 +1044,9 @@ public: template void enumerate(const std::vector& vector, typename std::enable_if::value || - std::is_same::value || - std::is_same::value || - std::is_same::value>::type* = 0) + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) { for (const T& item : vector) writeVal(item); @@ -1041,9 +1060,9 @@ public: template void enumerateLittle(const std::vector& vector, typename std::enable_if::value || - std::is_same::value || - std::is_same::value || - std::is_same::value>::type* = 0) + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) { for (const T& item : vector) writeValLittle(item); @@ -1057,9 +1076,9 @@ public: template void enumerateBig(const std::vector& vector, typename std::enable_if::value || - std::is_same::value || - std::is_same::value || - std::is_same::value>::type* = 0) + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) { for (const T& item : vector) writeValBig(item); @@ -1071,9 +1090,9 @@ public: template void enumerate(const std::vector& vector, typename std::enable_if::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value>::type* = 0) + !std::is_same::value && + !std::is_same::value && + !std::is_same::value>::type* = 0) { for (const T& item : vector) item.write(*this);