From b02a72a77bd7c33162b4622aa54e019dc54b6248 Mon Sep 17 00:00:00 2001 From: jacob1 Date: Fri, 28 Jul 2017 20:00:19 -0400 Subject: [PATCH] add length limit to authors on saving/loading, fix type issue causing mass duplication When making a local save, then stamping and loading the stamp (without doing anything else in between), issues with the code would cause the unsigned int in the json to turn into a normal int. It would then think the authors data from the stamp was from something else and append it. For users that do an excessive amount of stamping, this causes duplication in the authors links that shouldn't have ever happened. --- src/client/Client.cpp | 15 +++++++-------- src/client/GameSave.cpp | 21 ++++++++++++++------- src/client/GameSave.h | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 7669cf0c6..a4e957093 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -2023,16 +2023,15 @@ void Client::MergeStampAuthorInfo(Json::Value stampAuthors) // unless there is nothing loaded currently, then set authors directly if (authors.size()) { + // Don't add if it's exactly the same + if (stampAuthors["links"].size() == 1 && stampAuthors["links"][0] == Client::Ref().authors) + return; if (authors["username"] != stampAuthors["username"]) { - // Don't add if it's exactly the same - if (stampAuthors["links"].size() != 1 || stampAuthors["links"][0] != Client::Ref().authors) - { - // 2nd arg of MergeAuthorInfo needs to be an array - Json::Value toAdd; - toAdd.append(stampAuthors); - MergeAuthorInfo(toAdd); - } + // 2nd arg of MergeAuthorInfo needs to be an array + Json::Value toAdd; + toAdd.append(stampAuthors); + MergeAuthorInfo(toAdd); } else if (stampAuthors["links"].size()) { diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 50aa7dc65..ed38cee3c 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -2346,7 +2346,7 @@ fin: return (char*)outputData; } -void GameSave::ConvertBsonToJson(bson_iterator *iter, Json::Value *j) +void GameSave::ConvertBsonToJson(bson_iterator *iter, Json::Value *j, int depth) { bson_iterator subiter; bson_iterator_subiterator(iter, &subiter); @@ -2360,23 +2360,28 @@ void GameSave::ConvertBsonToJson(bson_iterator *iter, Json::Value *j) else if (bson_iterator_type(&subiter) == BSON_INT) (*j)[key] = bson_iterator_int(&subiter); else if (bson_iterator_type(&subiter) == BSON_LONG) - (*j)[key] = (Json::Value::Int64)bson_iterator_long(&subiter); - else if (bson_iterator_type(&subiter) == BSON_ARRAY) + (*j)[key] = (Json::Value::UInt64)bson_iterator_long(&subiter); + else if (bson_iterator_type(&subiter) == BSON_ARRAY && depth < 5) { bson_iterator arrayiter; bson_iterator_subiterator(&subiter, &arrayiter); + int length = 0, length2 = 0; while (bson_iterator_next(&arrayiter)) { if (bson_iterator_type(&arrayiter) == BSON_OBJECT && !strcmp(bson_iterator_key(&arrayiter), "part")) { Json::Value tempPart; - ConvertBsonToJson(&arrayiter, &tempPart); + ConvertBsonToJson(&arrayiter, &tempPart, depth + 1); (*j)["links"].append(tempPart); + length++; } else if (bson_iterator_type(&arrayiter) == BSON_INT && !strcmp(bson_iterator_key(&arrayiter), "saveID")) { (*j)["links"].append(bson_iterator_int(&arrayiter)); } + length2++; + if (length > (int)(40 / std::pow(depth+1, 2)) || length2 > 50) + break; } } } @@ -2422,14 +2427,15 @@ void GameSave::ConvertJsonToBson(bson *b, Json::Value j, int depth) bson_append_string(b, member.c_str(), j[member].asCString()); else if (j[member].isBool()) bson_append_bool(b, member.c_str(), j[member].asBool()); - else if (j[member].isInt() || j[member].isUInt()) + else if (j[member].type() == Json::intValue) bson_append_int(b, member.c_str(), j[member].asInt()); - else if (j[member].isInt64() || j[member].isUInt64()) + else if (j[member].type() == Json::uintValue) bson_append_long(b, member.c_str(), j[member].asInt64()); else if (j[member].isArray()) { bson_append_start_array(b, member.c_str()); std::set saveIDs = std::set(); + int length = 0; for (Json::Value::ArrayIndex i = 0; i < j[member].size(); i++) { // only supports objects and ints here because that is all we need @@ -2440,7 +2446,7 @@ void GameSave::ConvertJsonToBson(bson *b, Json::Value j, int depth) } if (!j[member][i].isObject()) continue; - if (depth > 4) + if (depth > 4 || length > (int)(40 / std::pow(depth+1, 2))) { std::set nestedSaveIDs = GetNestedSaveIDs(j[member][i]); saveIDs.insert(nestedSaveIDs.begin(), nestedSaveIDs.end()); @@ -2451,6 +2457,7 @@ void GameSave::ConvertJsonToBson(bson *b, Json::Value j, int depth) ConvertJsonToBson(b, j[member][i], depth+1); bson_append_finish_object(b); } + length++; } for (std::set::iterator iter = saveIDs.begin(), end = saveIDs.end(); iter != end; ++iter) { diff --git a/src/client/GameSave.h b/src/client/GameSave.h index 670aa9fa0..dd689572b 100644 --- a/src/client/GameSave.h +++ b/src/client/GameSave.h @@ -117,7 +117,7 @@ private: void readPSv(char * data, int dataLength); char * serialiseOPS(unsigned int & dataSize); void ConvertJsonToBson(bson *b, Json::Value j, int depth = 0); - void ConvertBsonToJson(bson_iterator *b, Json::Value *j); + void ConvertBsonToJson(bson_iterator *b, Json::Value *j, int depth = 0); }; #endif