add a limit to the size of deckfiles cockatrice can load (#7163)

* add a limit to the size of deckfiles cockatrice can load

the limit is 99999 or 100k -1 right now, which is kind of the limit of
what looks acceptable in the player

* format

* up limit to 100k because that's what the tests do
This commit is contained in:
ebbit1q 2026-08-29 15:21:04 +02:00 committed by GitHub
parent cf8e5858ab
commit 4b7b785452
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 29 additions and 19 deletions

View file

@ -5,6 +5,8 @@
#include <QCryptographicHash>
#include <QSet>
static constexpr int MAX_DECK_SIZE = 1e5;
DecklistNodeTree::DecklistNodeTree() : root(new InnerDecklistNode())
{
}
@ -113,7 +115,7 @@ void DecklistNodeTree::readZoneElement(QXmlStreamReader *xml)
{
QString zoneName = xml->attributes().value("name").toString();
InnerDecklistNode *newZone = getZoneObjFromName(zoneName);
newZone->readElement(xml);
totalCards += newZone->readElement(xml, MAX_DECK_SIZE - totalCards);
}
DecklistCardNode *DecklistNodeTree::addCard(const QString &cardName,
@ -125,6 +127,8 @@ DecklistCardNode *DecklistNodeTree::addCard(const QString &cardName,
const QString &cardProviderId,
const bool formatLegal)
{
amount = qMin(amount, MAX_DECK_SIZE - totalCards);
totalCards += amount;
auto *zoneNode = getZoneObjFromName(zoneName);
auto *node = new DecklistCardNode(cardName, amount, zoneNode, position, cardSetName, cardSetCollectorNumber,
cardProviderId, formatLegal);

View file

@ -10,6 +10,7 @@
class DecklistNodeTree
{
InnerDecklistNode *root; ///< Root of the deck tree (zones + cards).
int totalCards = 0;
public:
/** @brief Constructs an empty DecklistNodeTree. */

View file

@ -34,15 +34,15 @@ bool AbstractDecklistCardNode::compareName(AbstractDecklistNode *other) const
}
}
bool AbstractDecklistCardNode::readElement(QXmlStreamReader *xml)
int AbstractDecklistCardNode::readElement(QXmlStreamReader *xml, int /* limit */)
{
while (!xml->atEnd()) {
xml->readNext();
if (xml->isEndElement() && xml->name().toString() == "card") {
return false;
return 0;
}
}
return true;
return 0;
}
void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml)
@ -60,4 +60,4 @@ void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml)
if (!getCardProviderId().isEmpty()) {
xml->writeAttribute("uuid", getCardProviderId());
}
}
}

View file

@ -141,7 +141,7 @@ public:
*
* This supports loading deck files from Cockatrices XML format.
*/
bool readElement(QXmlStreamReader *xml) override;
int readElement(QXmlStreamReader *xml, int limit) override;
/**
* @brief Serialize this nodes properties to XML.

View file

@ -183,7 +183,7 @@ public:
* Cockatrice deck XML format.
* @{
*/
virtual bool readElement(QXmlStreamReader *xml) = 0;
virtual int readElement(QXmlStreamReader *xml, int limit) = 0;
virtual void writeElement(QXmlStreamWriter *xml) = 0;
/// @}
};

View file

@ -141,27 +141,31 @@ bool InnerDecklistNode::compareName(AbstractDecklistNode *other) const
}
}
bool InnerDecklistNode::readElement(QXmlStreamReader *xml)
int InnerDecklistNode::readElement(QXmlStreamReader *xml, int limit)
{
int totalCards = 0;
while (!xml->atEnd()) {
xml->readNext();
const QString childName = xml->name().toString();
if (xml->isStartElement()) {
if (childName == "zone") {
auto *newZone = new InnerDecklistNode(xml->attributes().value("name").toString(), this);
newZone->readElement(xml);
totalCards += newZone->readElement(xml, limit - totalCards);
} else if (childName == "card") {
auto *newCard = new DecklistCardNode(
xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(),
this, -1, xml->attributes().value("setShortName").toString(),
xml->attributes().value("collectorNumber").toString(), xml->attributes().value("uuid").toString());
newCard->readElement(xml);
int amount = xml->attributes().value("number").toString().toInt();
amount = qMin(amount, limit - totalCards);
auto *newCard = new DecklistCardNode(xml->attributes().value("name").toString(), amount, this, -1,
xml->attributes().value("setShortName").toString(),
xml->attributes().value("collectorNumber").toString(),
xml->attributes().value("uuid").toString());
totalCards += amount;
totalCards += newCard->readElement(xml, limit - totalCards);
}
} else if (xml->isEndElement() && (childName == "zone")) {
return false;
return totalCards;
}
}
return true;
return totalCards;
}
void InnerDecklistNode::writeElement(QXmlStreamWriter *xml)
@ -201,4 +205,4 @@ QVector<QPair<int, int>> InnerDecklistNode::sort(Qt::SortOrder order)
}
return result;
}
}

View file

@ -216,9 +216,10 @@ public:
/**
* @brief Deserialize this node and its children from XML.
* @param xml Reader positioned at this element.
* @return true if parsing succeeded.
* @param limit The maximum amount of cards to read
* @return the amount of cards found
*/
bool readElement(QXmlStreamReader *xml) override;
int readElement(QXmlStreamReader *xml, int limit) override;
/**
* @brief Serialize this node and its children to XML.