You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
Fix CatalogPagesListComposer parsing error in Nitro client
The Nitro client's NodeData parser enforces safety limits (max 1000 offers, 500 children, 20 depth) using Math.min() on the count but the server was sending all data beyond those limits. The unread bytes left in the buffer corrupted parsing of subsequent nodes, causing RangeError. Cap server-side output to match client limits and snapshot offerIds array to prevent potential race conditions between size() and iteration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+25
-10
@@ -15,6 +15,10 @@ import java.util.List;
|
|||||||
public class CatalogPagesListComposer extends MessageComposer {
|
public class CatalogPagesListComposer extends MessageComposer {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogPagesListComposer.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogPagesListComposer.class);
|
||||||
|
|
||||||
|
private static final int MAX_OFFERS = 1000;
|
||||||
|
private static final int MAX_CHILDREN = 500;
|
||||||
|
private static final int MAX_DEPTH = 20;
|
||||||
|
|
||||||
private final Habbo habbo;
|
private final Habbo habbo;
|
||||||
private final String mode;
|
private final String mode;
|
||||||
private final boolean hasPermission;
|
private final boolean hasPermission;
|
||||||
@@ -38,10 +42,12 @@ public class CatalogPagesListComposer extends MessageComposer {
|
|||||||
this.response.appendString("root");
|
this.response.appendString("root");
|
||||||
this.response.appendString("");
|
this.response.appendString("");
|
||||||
this.response.appendInt(0);
|
this.response.appendInt(0);
|
||||||
this.response.appendInt(pages.size());
|
|
||||||
|
|
||||||
for (CatalogPage category : pages) {
|
int childCount = Math.min(pages.size(), MAX_CHILDREN);
|
||||||
this.append(category);
|
this.response.appendInt(childCount);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < childCount; idx++) {
|
||||||
|
this.append(pages.get(idx), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.response.appendBoolean(false);
|
this.response.appendBoolean(false);
|
||||||
@@ -55,7 +61,7 @@ public class CatalogPagesListComposer extends MessageComposer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void append(CatalogPage category) {
|
private void append(CatalogPage category, int depth) {
|
||||||
List<CatalogPage> pagesList = Emulator.getGameEnvironment().getCatalogManager().getCatalogPages(category.getId(), this.habbo);
|
List<CatalogPage> pagesList = Emulator.getGameEnvironment().getCatalogManager().getCatalogPages(category.getId(), this.habbo);
|
||||||
|
|
||||||
this.response.appendBoolean(category.isVisible());
|
this.response.appendBoolean(category.isVisible());
|
||||||
@@ -63,16 +69,25 @@ public class CatalogPagesListComposer extends MessageComposer {
|
|||||||
this.response.appendInt(category.isEnabled() ? category.getId() : -1);
|
this.response.appendInt(category.isEnabled() ? category.getId() : -1);
|
||||||
this.response.appendString(category.getPageName());
|
this.response.appendString(category.getPageName());
|
||||||
this.response.appendString(category.getCaption() + (this.hasPermission ? " (" + category.getId() + ")" : ""));
|
this.response.appendString(category.getCaption() + (this.hasPermission ? " (" + category.getId() + ")" : ""));
|
||||||
this.response.appendInt(category.getOfferIds().size());
|
|
||||||
|
|
||||||
for (int i : category.getOfferIds().toArray()) {
|
int[] offers = category.getOfferIds().toArray();
|
||||||
this.response.appendInt(i);
|
int offerCount = Math.min(offers.length, MAX_OFFERS);
|
||||||
|
this.response.appendInt(offerCount);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < offerCount; idx++) {
|
||||||
|
this.response.appendInt(offers[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.response.appendInt(pagesList.size());
|
if (depth >= MAX_DEPTH) {
|
||||||
|
this.response.appendInt(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (CatalogPage page : pagesList) {
|
int childCount = Math.min(pagesList.size(), MAX_CHILDREN);
|
||||||
this.append(page);
|
this.response.appendInt(childCount);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < childCount; idx++) {
|
||||||
|
this.append(pagesList.get(idx), depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user