libragephoto: improve get and serializer reliability

- get functions do not return NULL or nullptr anymore
- serializer checks for valid references to not crash
- tight buffers do not prematurely end writing anymore
- add zeroBuffer function for future nullbyte insertions
- IconvTest.cpp: remove some C-style casts
- RagePhoto.cpp: improve initializer reliability
- RagePhotoA.hpp: throw error when instance could not be allocated
- README.md: minor markdown fix
This commit is contained in:
Syping 2023-10-30 14:31:50 +01:00
parent c74b4a415f
commit 9a5bcabf8c
6 changed files with 224 additions and 118 deletions

View file

@ -17,7 +17,7 @@
****************************************************************************]] ****************************************************************************]]
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.8)
project(ragephoto VERSION 0.5.1 LANGUAGES C CXX) project(ragephoto VERSION 0.6.0 LANGUAGES C CXX)
include(GNUInstallDirs) include(GNUInstallDirs)
# RagePhoto CMake includes # RagePhoto CMake includes

View file

@ -56,6 +56,19 @@ inline size_t writeBuffer(const void *input, char *output, size_t *pos, size_t o
return writeLen; return writeLen;
} }
inline size_t zeroBuffer(char *output, size_t *pos, size_t outputLen, size_t inputLen)
{
const size_t maxLen = outputLen - *pos;
size_t zeroLen = inputLen;
if (*pos >= outputLen)
return 0;
if (inputLen > maxLen)
zeroLen = maxLen;
memset(&output[*pos], 0, zeroLen);
*pos = *pos + zeroLen;
return zeroLen;
}
inline bool writeDataChar(const char *input, char **output) inline bool writeDataChar(const char *input, char **output)
{ {
const size_t src_s = strlen(input) + 1; const size_t src_s = strlen(input) + 1;
@ -247,7 +260,7 @@ bool ragephotodata_load(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser
char *dst = rp_data->header; char *dst = rp_data->header;
const size_t ret = iconv(iconv_in, &src, &src_s, &dst, &dst_s); const size_t ret = iconv(iconv_in, &src, &src_s, &dst, &dst_s);
iconv_close(iconv_in); iconv_close(iconv_in);
if (ret == (size_t)(-1)) { if (ret == (size_t)-1) {
rp_data->error = RAGEPHOTO_ERROR_UNICODEHEADERERROR; // 6 rp_data->error = RAGEPHOTO_ERROR_UNICODEHEADERERROR; // 6
return false; return false;
} }
@ -257,7 +270,7 @@ bool ragephotodata_load(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser
rp_data->error = RAGEPHOTO_ERROR_HEADERMALLOCERROR; // 4 rp_data->error = RAGEPHOTO_ERROR_HEADERMALLOCERROR; // 4
return false; return false;
} }
const int converted = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)(photoHeader), -1, rp_data->header, 256, NULL, NULL); const int converted = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)photoHeader, -1, rp_data->header, 256, NULL, NULL);
if (converted == 0) { if (converted == 0) {
free(rp_data->header); free(rp_data->header);
rp_data->header = NULL; rp_data->header = NULL;
@ -619,17 +632,20 @@ uint32_t ragephoto_getphotoformat(ragephoto_t instance_t)
const char* ragephoto_getphotojpeg(ragephoto_t instance_t) const char* ragephoto_getphotojpeg(ragephoto_t instance_t)
{ {
RagePhotoInstance *instance = (RagePhotoInstance*)instance_t; RagePhotoInstance *instance = (RagePhotoInstance*)instance_t;
return instance->data->jpeg; if (instance->data->jpeg)
return instance->data->jpeg;
return "";
} }
uint64_t ragephotodata_getphotosignf(RagePhotoData *rp_data, uint32_t photoFormat) uint64_t ragephotodata_getphotosignf(RagePhotoData *rp_data, uint32_t photoFormat)
{ {
if (photoFormat == RAGEPHOTO_FORMAT_GTA5) if (rp_data->jpeg) {
return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, RAGEPHOTO_SIGNINITIAL_GTA5)); if (photoFormat == RAGEPHOTO_FORMAT_GTA5)
else if (photoFormat == RAGEPHOTO_FORMAT_RDR2) return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, RAGEPHOTO_SIGNINITIAL_GTA5));
return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, RAGEPHOTO_SIGNINITIAL_RDR2)); else if (photoFormat == RAGEPHOTO_FORMAT_RDR2)
else return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, RAGEPHOTO_SIGNINITIAL_RDR2));
return 0; }
return 0;
} }
uint64_t ragephotodata_getphotosign(RagePhotoData *rp_data) uint64_t ragephotodata_getphotosign(RagePhotoData *rp_data)
@ -654,32 +670,39 @@ uint32_t ragephoto_getphotosize(ragephoto_t instance_t)
RagePhotoInstance *instance = (RagePhotoInstance*)instance_t; RagePhotoInstance *instance = (RagePhotoInstance*)instance_t;
if (instance->data->jpeg) if (instance->data->jpeg)
return instance->data->jpegSize; return instance->data->jpegSize;
else return 0;
return 0;
} }
const char* ragephoto_getphotodesc(ragephoto_t instance_t) const char* ragephoto_getphotodesc(ragephoto_t instance_t)
{ {
RagePhotoInstance *instance = (RagePhotoInstance*)instance_t; RagePhotoInstance *instance = (RagePhotoInstance*)instance_t;
return instance->data->description; if (instance->data->description)
return instance->data->description;
return "";
} }
const char* ragephoto_getphotojson(ragephoto_t instance_t) const char* ragephoto_getphotojson(ragephoto_t instance_t)
{ {
RagePhotoInstance *instance = (RagePhotoInstance*)instance_t; RagePhotoInstance *instance = (RagePhotoInstance*)instance_t;
return instance->data->json; if (instance->data->json)
return instance->data->json;
return "";
} }
const char* ragephoto_getphotoheader(ragephoto_t instance_t) const char* ragephoto_getphotoheader(ragephoto_t instance_t)
{ {
RagePhotoInstance *instance = (RagePhotoInstance*)instance_t; RagePhotoInstance *instance = (RagePhotoInstance*)instance_t;
return instance->data->header; if (instance->data->header)
return instance->data->header;
return "";
} }
const char* ragephoto_getphototitle(ragephoto_t instance_t) const char* ragephoto_getphototitle(ragephoto_t instance_t)
{ {
RagePhotoInstance *instance = (RagePhotoInstance*)instance_t; RagePhotoInstance *instance = (RagePhotoInstance*)instance_t;
return instance->data->title; if (instance->data->title)
return instance->data->title;
return "";
} }
const char* ragephoto_version() const char* ragephoto_version()
@ -690,6 +713,10 @@ const char* ragephoto_version()
bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser, char *data, uint32_t photoFormat) bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser, char *data, uint32_t photoFormat)
{ {
if (photoFormat == RAGEPHOTO_FORMAT_GTA5 || photoFormat == RAGEPHOTO_FORMAT_RDR2) { if (photoFormat == RAGEPHOTO_FORMAT_GTA5 || photoFormat == RAGEPHOTO_FORMAT_RDR2) {
if (!rp_data->header) {
rp_data->error = RAGEPHOTO_ERROR_INCOMPLETEHEADER; // 3
return false;
}
#if defined(UNICODE_ICONV) || defined(UNICODE_WINCVT) #if defined(UNICODE_ICONV) || defined(UNICODE_WINCVT)
#if defined(UNICODE_ICONV) #if defined(UNICODE_ICONV)
iconv_t iconv_in = iconv_open("UTF-16LE", "UTF-8"); iconv_t iconv_in = iconv_open("UTF-16LE", "UTF-8");
@ -705,7 +732,7 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
char *dst = photoHeader; char *dst = photoHeader;
const size_t ret = iconv(iconv_in, &src, &src_s, &dst, &dst_s); const size_t ret = iconv(iconv_in, &src, &src_s, &dst, &dst_s);
iconv_close(iconv_in); iconv_close(iconv_in);
if (ret == (size_t)(-1)) { if (ret == (size_t)-1) {
rp_data->error = RAGEPHOTO_ERROR_UNICODEHEADERERROR; // 6 rp_data->error = RAGEPHOTO_ERROR_UNICODEHEADERERROR; // 6
return false; return false;
} }
@ -713,7 +740,7 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
#elif defined(UNICODE_WINCVT) #elif defined(UNICODE_WINCVT)
char photoHeader[256]; char photoHeader[256];
memset(&photoHeader, 0, 256); memset(&photoHeader, 0, 256);
const int converted = MultiByteToWideChar(CP_UTF8, 0, rp_data->header, (int)(strlen(rp_data->header)), (wchar_t*)(photoHeader), 256 / sizeof(wchar_t)); const int converted = MultiByteToWideChar(CP_UTF8, 0, rp_data->header, (int)strlen(rp_data->header), (wchar_t*)photoHeader, 256 / sizeof(wchar_t));
if (converted == 0) { if (converted == 0) {
rp_data->error = RAGEPHOTO_ERROR_UNICODEHEADERERROR; // 6 rp_data->error = RAGEPHOTO_ERROR_UNICODEHEADERERROR; // 6
return false; return false;
@ -721,29 +748,6 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
const size_t photoHeader_size = 256; const size_t photoHeader_size = 256;
#endif #endif
if (rp_data->jpegSize > rp_data->jpegBuffer) {
rp_data->error = RAGEPHOTO_ERROR_PHOTOBUFFERTIGHT; // 36
return false;
}
const size_t jsonString_size = strlen(rp_data->json) + 1;
if (jsonString_size > rp_data->jsonBuffer) {
rp_data->error = RAGEPHOTO_ERROR_JSONBUFFERTIGHT; // 37
return false;
}
const size_t titlString_size = strlen(rp_data->title) + 1;
if (titlString_size > rp_data->titlBuffer) {
rp_data->error = RAGEPHOTO_ERROR_TITLEBUFFERTIGHT; // 38
return false;
}
const size_t descString_size = strlen(rp_data->description) + 1;
if (descString_size > rp_data->descBuffer) {
rp_data->error = RAGEPHOTO_ERROR_DESCBUFFERTIGHT; // 39
return false;
}
const size_t length = ragephotodata_getsavesizef(rp_data, rp_parser, photoFormat); const size_t length = ragephotodata_getsavesizef(rp_data, rp_parser, photoFormat);
size_t pos = 0; size_t pos = 0;
char uInt32Buffer[4]; char uInt32Buffer[4];
@ -751,7 +755,7 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(uInt32Buffer, &photoFormat, 4); memcpy(uInt32Buffer, &photoFormat, 4);
#else #else
uInt32ToCharLE((uint32_t)(photoFormat), uInt32Buffer); uInt32ToCharLE(photoFormat, uInt32Buffer);
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
@ -825,9 +829,20 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->jpeg, data, &pos, length, rp_data->jpegSize); if (rp_data->jpeg) {
for (size_t i = rp_data->jpegSize; i < rp_data->jpegBuffer; i++) { if (rp_data->jpegSize > rp_data->jpegBuffer) {
writeBuffer("\0", data, &pos, length, 1); rp_data->error = RAGEPHOTO_ERROR_PHOTOBUFFERTIGHT; // 36
return false;
}
writeBuffer(rp_data->jpeg, data, &pos, length, rp_data->jpegSize);
for (size_t i = rp_data->jpegSize; i < rp_data->jpegBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->jpegBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->jsonOffset + headerSize; pos = rp_data->jsonOffset + headerSize;
@ -840,9 +855,21 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->json, data, &pos, length, jsonString_size); if (rp_data->json) {
for (size_t i = jsonString_size; i < rp_data->jsonBuffer; i++) { const size_t jsonString_size = strlen(rp_data->json) + 1;
writeBuffer("\0", data, &pos, length, 1); if (jsonString_size > rp_data->jsonBuffer) {
rp_data->error = RAGEPHOTO_ERROR_JSONBUFFERTIGHT; // 37
return false;
}
writeBuffer(rp_data->json, data, &pos, length, jsonString_size);
for (size_t i = jsonString_size; i < rp_data->jsonBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->jsonBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->titlOffset + headerSize; pos = rp_data->titlOffset + headerSize;
@ -855,9 +882,21 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->title, data, &pos, length, titlString_size); if (rp_data->title) {
for (size_t i = titlString_size; i < rp_data->titlBuffer; i++) { const size_t titlString_size = strlen(rp_data->title) + 1;
writeBuffer("\0", data, &pos, length, 1); if (titlString_size > rp_data->titlBuffer) {
rp_data->error = RAGEPHOTO_ERROR_TITLEBUFFERTIGHT; // 38
return false;
}
writeBuffer(rp_data->title, data, &pos, length, titlString_size);
for (size_t i = titlString_size; i < rp_data->titlBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->titlBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->descOffset + headerSize; pos = rp_data->descOffset + headerSize;
@ -870,9 +909,21 @@ bool ragephotodata_savef(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parse
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->description, data, &pos, length, descString_size); if (rp_data->description) {
for (size_t i = descString_size; i < rp_data->descBuffer; i++) { const size_t descString_size = strlen(rp_data->description) + 1;
writeBuffer("\0", data, &pos, length, 1); if (descString_size > rp_data->descBuffer) {
rp_data->error = RAGEPHOTO_ERROR_DESCBUFFERTIGHT; // 39
return false;
}
writeBuffer(rp_data->description, data, &pos, length, descString_size);
for (size_t i = descString_size; i < rp_data->descBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->descBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->endOfFile + headerSize - 4; pos = rp_data->endOfFile + headerSize - 4;

View file

@ -72,6 +72,19 @@ inline size_t writeBuffer(const void *input, char *output, size_t *pos, size_t o
return writeLen; return writeLen;
} }
inline size_t zeroBuffer(char *output, size_t *pos, size_t outputLen, size_t inputLen)
{
const size_t maxLen = outputLen - *pos;
size_t zeroLen = inputLen;
if (*pos >= outputLen)
return 0;
if (inputLen > maxLen)
zeroLen = maxLen;
memset(&output[*pos], 0, zeroLen);
*pos = *pos + zeroLen;
return zeroLen;
}
inline bool writeDataChar(const char *input, char **output) inline bool writeDataChar(const char *input, char **output)
{ {
const size_t src_s = strlen(input) + 1; const size_t src_s = strlen(input) + 1;
@ -144,12 +157,16 @@ inline uint32_t joaatFromInitial(const char *data, size_t size, uint32_t init_va
RagePhoto::RagePhoto() RagePhoto::RagePhoto()
{ {
m_data = static_cast<RagePhotoData*>(malloc(sizeof(RagePhotoData))); m_data = static_cast<RagePhotoData*>(malloc(sizeof(RagePhotoData)));
if (!m_data) if (!m_data) {
throw std::runtime_error("RagePhotoData data struct can't be allocated"); throw std::runtime_error("RagePhotoData data struct can't be allocated");
return;
}
memset(m_data, 0, sizeof(RagePhotoData)); memset(m_data, 0, sizeof(RagePhotoData));
m_parser = static_cast<RagePhotoFormatParser*>(malloc(sizeof(RagePhotoFormatParser))); m_parser = static_cast<RagePhotoFormatParser*>(malloc(sizeof(RagePhotoFormatParser)));
if (!m_parser) if (!m_parser) {
throw std::runtime_error("RagePhotoFormatParser parser struct can't be allocated"); throw std::runtime_error("RagePhotoFormatParser parser struct can't be allocated");
return;
}
memset(m_parser, 0, sizeof(RagePhotoFormatParser)); memset(m_parser, 0, sizeof(RagePhotoFormatParser));
setBufferDefault(m_data); setBufferDefault(m_data);
} }
@ -621,8 +638,7 @@ const std::string RagePhoto::jpeg() const
{ {
if (m_data->jpeg) if (m_data->jpeg)
return std::string(m_data->jpeg, m_data->jpegSize); return std::string(m_data->jpeg, m_data->jpegSize);
else return std::string();
return std::string();
} }
#if (RAGEPHOTO_CXX_STD >= 17) && (__cplusplus >= 201703L) #if (RAGEPHOTO_CXX_STD >= 17) && (__cplusplus >= 201703L)
@ -630,24 +646,26 @@ const std::string_view RagePhoto::jpeg_view() const
{ {
if (m_data->jpeg) if (m_data->jpeg)
return std::string_view(m_data->jpeg, m_data->jpegSize); return std::string_view(m_data->jpeg, m_data->jpegSize);
else return std::string_view();
return std::string_view();
} }
#endif #endif
const char* RagePhoto::jpegData() const const char* RagePhoto::jpegData() const
{ {
return m_data->jpeg; if (m_data->jpeg)
return m_data->jpeg;
return "";
} }
uint64_t RagePhoto::jpegSign(uint32_t photoFormat, RagePhotoData *rp_data) uint64_t RagePhoto::jpegSign(uint32_t photoFormat, RagePhotoData *rp_data)
{ {
if (photoFormat == PhotoFormat::GTA5) if (rp_data->jpeg) {
return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, SignInitials::SIGTA5)); if (photoFormat == PhotoFormat::GTA5)
else if (photoFormat == PhotoFormat::RDR2) return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, SignInitials::SIGTA5));
return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, SignInitials::SIRDR2)); else if (photoFormat == PhotoFormat::RDR2)
else return (0x100000000000000ULL | joaatFromInitial(rp_data->jpeg, rp_data->jpegSize, SignInitials::SIRDR2));
return 0; }
return 0;
} }
uint64_t RagePhoto::jpegSign(RagePhotoData *rp_data) uint64_t RagePhoto::jpegSign(RagePhotoData *rp_data)
@ -669,28 +687,35 @@ uint32_t RagePhoto::jpegSize() const
{ {
if (m_data->jpeg) if (m_data->jpeg)
return m_data->jpegSize; return m_data->jpegSize;
else return 0;
return 0;
} }
const char* RagePhoto::description() const const char* RagePhoto::description() const
{ {
return m_data->description; if (m_data->description)
return m_data->description;
return "";
} }
const char* RagePhoto::json() const const char* RagePhoto::json() const
{ {
return m_data->json; if (m_data->json)
return m_data->json;
return "";
} }
const char* RagePhoto::header() const const char* RagePhoto::header() const
{ {
return m_data->header; if (m_data->header)
return m_data->header;
return "";
} }
const char* RagePhoto::title() const const char* RagePhoto::title() const
{ {
return m_data->title; if (m_data->title)
return m_data->title;
return "";
} }
const char* RagePhoto::version() const char* RagePhoto::version()
@ -701,6 +726,10 @@ const char* RagePhoto::version()
bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser) bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser)
{ {
if (photoFormat == PhotoFormat::GTA5 || photoFormat == PhotoFormat::RDR2) { if (photoFormat == PhotoFormat::GTA5 || photoFormat == PhotoFormat::RDR2) {
if (!rp_data->header) {
rp_data->error = Error::IncompleteHeader; // 3
return false;
}
#if defined UNICODE_ICONV || defined UNICODE_CODECVT || defined UNICODE_WINCVT #if defined UNICODE_ICONV || defined UNICODE_CODECVT || defined UNICODE_WINCVT
#if defined UNICODE_CODECVT #if defined UNICODE_CODECVT
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert; std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
@ -709,7 +738,7 @@ bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, R
rp_data->error = Error::UnicodeHeaderError; // 6 rp_data->error = Error::UnicodeHeaderError; // 6
return false; return false;
} }
const size_t photoHeader_size = photoHeader_string.size() * 2; const size_t photoHeader_size = photoHeader_string.size() * sizeof(char16_t);
if (photoHeader_size > 256) { if (photoHeader_size > 256) {
rp_data->error = Error::HeaderBufferTight; // 35 rp_data->error = Error::HeaderBufferTight; // 35
return false; return false;
@ -743,29 +772,6 @@ bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, R
const size_t photoHeader_size = 256; const size_t photoHeader_size = 256;
#endif #endif
if (rp_data->jpegSize > rp_data->jpegBuffer) {
rp_data->error = Error::PhotoBufferTight; // 36
return false;
}
const size_t jsonString_size = strlen(rp_data->json) + 1;
if (jsonString_size > rp_data->jsonBuffer) {
rp_data->error = Error::JsonBufferTight; // 37
return false;
}
const size_t titlString_size = strlen(rp_data->title) + 1;
if (titlString_size > rp_data->titlBuffer) {
rp_data->error = Error::TitleBufferTight; // 38
return false;
}
const size_t descString_size = strlen(rp_data->description) + 1;
if (descString_size > rp_data->descBuffer) {
rp_data->error = Error::DescBufferTight; // 39
return false;
}
const size_t length = saveSize(photoFormat, rp_data, rp_parser); const size_t length = saveSize(photoFormat, rp_data, rp_parser);
size_t pos = 0; size_t pos = 0;
char uInt32Buffer[4]; char uInt32Buffer[4];
@ -773,7 +779,7 @@ bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, R
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(uInt32Buffer, &photoFormat, 4); memcpy(uInt32Buffer, &photoFormat, 4);
#else #else
uInt32ToCharLE(static_cast<uint32_t>(photoFormat), uInt32Buffer); uInt32ToCharLE(photoFormat, uInt32Buffer);
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
@ -846,9 +852,20 @@ bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, R
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->jpeg, data, &pos, length, rp_data->jpegSize); if (rp_data->jpeg) {
for (size_t i = rp_data->jpegSize; i < rp_data->jpegBuffer; i++) { if (rp_data->jpegSize > rp_data->jpegBuffer) {
writeBuffer("\0", data, &pos, length, 1); rp_data->error = Error::PhotoBufferTight; // 36
return false;
}
writeBuffer(rp_data->jpeg, data, &pos, length, rp_data->jpegSize);
for (size_t i = rp_data->jpegSize; i < rp_data->jpegBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->jpegBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->jsonOffset + headerSize; pos = rp_data->jsonOffset + headerSize;
@ -861,9 +878,21 @@ bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, R
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->json, data, &pos, length, jsonString_size); if (rp_data->json) {
for (size_t i = jsonString_size; i < rp_data->jsonBuffer; i++) { const size_t jsonString_size = strlen(rp_data->json) + 1;
writeBuffer("\0", data, &pos, length, 1); if (jsonString_size > rp_data->jsonBuffer) {
rp_data->error = Error::JsonBufferTight; // 37
return false;
}
writeBuffer(rp_data->json, data, &pos, length, jsonString_size);
for (size_t i = jsonString_size; i < rp_data->jsonBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->jsonBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->titlOffset + headerSize; pos = rp_data->titlOffset + headerSize;
@ -876,9 +905,21 @@ bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, R
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->title, data, &pos, length, titlString_size); if (rp_data->title) {
for (size_t i = titlString_size; i < rp_data->titlBuffer; i++) { const size_t titlString_size = strlen(rp_data->title) + 1;
writeBuffer("\0", data, &pos, length, 1); if (titlString_size > rp_data->titlBuffer) {
rp_data->error = Error::TitleBufferTight; // 38
return false;
}
writeBuffer(rp_data->title, data, &pos, length, titlString_size);
for (size_t i = titlString_size; i < rp_data->titlBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->titlBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->descOffset + headerSize; pos = rp_data->descOffset + headerSize;
@ -891,9 +932,21 @@ bool RagePhoto::save(char *data, uint32_t photoFormat, RagePhotoData *rp_data, R
#endif #endif
writeBuffer(uInt32Buffer, data, &pos, length, 4); writeBuffer(uInt32Buffer, data, &pos, length, 4);
writeBuffer(rp_data->description, data, &pos, length, descString_size); if (rp_data->description) {
for (size_t i = descString_size; i < rp_data->descBuffer; i++) { const size_t descString_size = strlen(rp_data->description) + 1;
writeBuffer("\0", data, &pos, length, 1); if (descString_size > rp_data->descBuffer) {
rp_data->error = Error::DescBufferTight; // 39
return false;
}
writeBuffer(rp_data->description, data, &pos, length, descString_size);
for (size_t i = descString_size; i < rp_data->descBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
}
else {
for (size_t i = 0; i < rp_data->descBuffer; i++) {
writeBuffer("\0", data, &pos, length, 1);
}
} }
pos = rp_data->endOfFile + headerSize - 4; pos = rp_data->endOfFile + headerSize - 4;

View file

@ -96,6 +96,8 @@ public:
}; };
RagePhotoA() { RagePhotoA() {
instance = ragephoto_open(); instance = ragephoto_open();
if (!instance)
throw std::runtime_error("ragephoto_t instance can't be allocated");
} }
~RagePhotoA() { ~RagePhotoA() {
ragephoto_close(instance); ragephoto_close(instance);

View file

@ -206,7 +206,7 @@ int main(int argc, char *argv[])
// English // English
src_s = sizeof(photoHeader_english); src_s = sizeof(photoHeader_english);
dst_s = sizeof(photoString); dst_s = sizeof(photoString);
char *src_english = (char*)photoHeader_english; char *src_english = reinterpret_cast<char*>(photoHeader_english);
char *dst_english = photoString; char *dst_english = photoString;
ret = iconv(iconv_in, &src_english, &src_s, &dst_english, &dst_s); ret = iconv(iconv_in, &src_english, &src_s, &dst_english, &dst_s);
if (ret == static_cast<size_t>(-1)) if (ret == static_cast<size_t>(-1))
@ -217,7 +217,7 @@ int main(int argc, char *argv[])
// Japanese // Japanese
src_s = sizeof(photoHeader_japanese); src_s = sizeof(photoHeader_japanese);
dst_s = sizeof(photoString); dst_s = sizeof(photoString);
char *src_japanese = (char*)photoHeader_japanese; char *src_japanese = reinterpret_cast<char*>(photoHeader_japanese);
char *dst_japanese = photoString; char *dst_japanese = photoString;
ret = iconv(iconv_in, &src_japanese, &src_s, &dst_japanese, &dst_s); ret = iconv(iconv_in, &src_japanese, &src_s, &dst_japanese, &dst_s);
if (ret == static_cast<size_t>(-1)) if (ret == static_cast<size_t>(-1))
@ -228,7 +228,7 @@ int main(int argc, char *argv[])
// Korean // Korean
src_s = sizeof(photoHeader_korean); src_s = sizeof(photoHeader_korean);
dst_s = sizeof(photoString); dst_s = sizeof(photoString);
char *src_korean = (char*)photoHeader_korean; char *src_korean = reinterpret_cast<char*>(photoHeader_korean);
char *dst_korean = photoString; char *dst_korean = photoString;
ret = iconv(iconv_in, &src_korean, &src_s, &dst_korean, &dst_s); ret = iconv(iconv_in, &src_korean, &src_s, &dst_korean, &dst_s);
if (ret == static_cast<size_t>(-1)) if (ret == static_cast<size_t>(-1))
@ -239,7 +239,7 @@ int main(int argc, char *argv[])
// Russian // Russian
src_s = sizeof(photoHeader_russian); src_s = sizeof(photoHeader_russian);
dst_s = sizeof(photoString); dst_s = sizeof(photoString);
char *src_russian = (char*)photoHeader_russian; char *src_russian = reinterpret_cast<char*>(photoHeader_russian);
char *dst_russian = photoString; char *dst_russian = photoString;
ret = iconv(iconv_in, &src_russian, &src_s, &dst_russian, &dst_s); ret = iconv(iconv_in, &src_russian, &src_s, &dst_russian, &dst_s);
if (ret == static_cast<size_t>(-1)) if (ret == static_cast<size_t>(-1))
@ -250,7 +250,7 @@ int main(int argc, char *argv[])
// Taiwanese // Taiwanese
src_s = sizeof(photoHeader_taiwanese); src_s = sizeof(photoHeader_taiwanese);
dst_s = sizeof(photoString); dst_s = sizeof(photoString);
char *src_taiwanese = (char*)photoHeader_taiwanese; char *src_taiwanese = reinterpret_cast<char*>(photoHeader_taiwanese);
char *dst_taiwanese = photoString; char *dst_taiwanese = photoString;
ret = iconv(iconv_in, &src_taiwanese, &src_s, &dst_taiwanese, &dst_s); ret = iconv(iconv_in, &src_taiwanese, &src_s, &dst_taiwanese, &dst_s);
if (ret == static_cast<size_t>(-1)) if (ret == static_cast<size_t>(-1))