From 47ed05fef1674e690e0beb348ae07ac835c05642 Mon Sep 17 00:00:00 2001 From: Alex Thomson Date: Wed, 30 Jan 2019 18:55:06 +1300 Subject: [PATCH] Enforce Gui limit for books Limits books to 50 pages with 255 characters for each. Anything outside of the limits will be automatically removed Reference: https://github.com/SpongePowered/SpongeCommon/issues/2156 --- .../lxgaming/sledgehammer/Sledgehammer.java | 2 + .../configuration/category/MixinCategory.java | 7 ++ .../core/item/MixinItemWritableBook.java | 71 +++++++++++++++++++ .../MixinNetHandlerPlayServer_Book.java | 62 ++++++++++++++++ .../resources/mixins.sledgehammer.core.json | 2 + 5 files changed, 144 insertions(+) create mode 100644 src/main/java/io/github/lxgaming/sledgehammer/mixin/core/item/MixinItemWritableBook.java create mode 100644 src/main/java/io/github/lxgaming/sledgehammer/mixin/core/network/MixinNetHandlerPlayServer_Book.java diff --git a/src/main/java/io/github/lxgaming/sledgehammer/Sledgehammer.java b/src/main/java/io/github/lxgaming/sledgehammer/Sledgehammer.java index f114cf1..1275113 100644 --- a/src/main/java/io/github/lxgaming/sledgehammer/Sledgehammer.java +++ b/src/main/java/io/github/lxgaming/sledgehammer/Sledgehammer.java @@ -71,6 +71,8 @@ private void registerMappings() { getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.block.MixinBlockIce", MixinCategory::isBlockIce); getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.entity.MixinEntity_Teleport", MixinCategory::isItemTeleport); getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.item.MixinItemStack_Exploit", MixinCategory::isItemstackExploit); + getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.item.MixinItemWritableBook", MixinCategory::isLimitBooks); + getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.network.MixinNetHandlerPlayServer_Book", MixinCategory::isLimitBooks); getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.network.MixinNetHandlerPlayServer_Event", MixinCategory::isInteractEvents); getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.network.MixinNetworkManager", MixinCategory::isFlushNetworkOnTick); getMixinMappings().put("io.github.lxgaming.sledgehammer.mixin.core.network.MixinNetworkSystem", MixinCategory::isNetworkSystem); diff --git a/src/main/java/io/github/lxgaming/sledgehammer/configuration/category/MixinCategory.java b/src/main/java/io/github/lxgaming/sledgehammer/configuration/category/MixinCategory.java index 3019af3..96230da 100644 --- a/src/main/java/io/github/lxgaming/sledgehammer/configuration/category/MixinCategory.java +++ b/src/main/java/io/github/lxgaming/sledgehammer/configuration/category/MixinCategory.java @@ -52,6 +52,9 @@ public class MixinCategory { @Setting(value = "itemstack-exploit", comment = "Fixes MC-134716") private boolean itemstackExploit = false; + @Setting(value = "limit-books", comment = "Limits books to 50 pages with 255 characters for each") + private boolean limitBooks = false; + @Setting(value = "network-system", comment = "Fixes potential deadlock on shutdown") private boolean networkSystem = false; @@ -103,6 +106,10 @@ public boolean isItemstackExploit() { return itemstackExploit; } + public boolean isLimitBooks() { + return limitBooks; + } + public boolean isNetworkSystem() { return networkSystem; } diff --git a/src/main/java/io/github/lxgaming/sledgehammer/mixin/core/item/MixinItemWritableBook.java b/src/main/java/io/github/lxgaming/sledgehammer/mixin/core/item/MixinItemWritableBook.java new file mode 100644 index 0000000..447ef4b --- /dev/null +++ b/src/main/java/io/github/lxgaming/sledgehammer/mixin/core/item/MixinItemWritableBook.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Alex Thomson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.lxgaming.sledgehammer.mixin.core.item; + +import net.minecraft.item.ItemWritableBook; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import org.apache.commons.lang3.StringUtils; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(value = ItemWritableBook.class, priority = 1337) +public abstract class MixinItemWritableBook { + + /** + * @param compound NBTTagCompound + * @author LX_Gaming + * @reason Limit books based on {@link net.minecraft.client.gui.GuiScreenBook GuiScreenBook} values. + */ + @Overwrite + public static boolean isNBTValid(NBTTagCompound compound) { + // TAG_LIST + if (compound == null || !compound.hasKey("pages", 9)) { + return false; + } + + // TAG_STRING + NBTTagList pages = compound.getTagList("pages", 8); + + // net.minecraft.item.ItemWrittenBook#resolveContents(ItemStack, EntityPlayer) + if (compound.getBoolean("resolved")) { + for (int index = 0; index < pages.tagCount(); index++) { + if (pages.getStringTagAt(index).length() > 32767) { + return false; + } + } + + return true; + } + + for (int index = 0; index < pages.tagCount(); index++) { + if (index >= 50) { + pages.removeTag(index); + index--; + continue; + } + + String page = pages.getStringTagAt(index); + if (page.length() >= 256) { + pages.set(index, new NBTTagString(StringUtils.truncate(page, 252) + "...")); + } + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/sledgehammer/mixin/core/network/MixinNetHandlerPlayServer_Book.java b/src/main/java/io/github/lxgaming/sledgehammer/mixin/core/network/MixinNetHandlerPlayServer_Book.java new file mode 100644 index 0000000..3ef74a6 --- /dev/null +++ b/src/main/java/io/github/lxgaming/sledgehammer/mixin/core/network/MixinNetHandlerPlayServer_Book.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Alex Thomson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.lxgaming.sledgehammer.mixin.core.network; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.client.CPacketCustomPayload; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(value = NetHandlerPlayServer.class, priority = 137) +public abstract class MixinNetHandlerPlayServer_Book { + + @Inject(method = "processCustomPayload", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/item/ItemWritableBook;isNBTValid(Lnet/minecraft/nbt/NBTTagCompound;)Z" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void onIsNBTValid(CPacketCustomPayload packet, CallbackInfo callbackInfo, + String channelName, PacketBuffer packetBuffer, ItemStack itemStack) { + NBTTagCompound compound = itemStack.getTagCompound(); + if (compound != null) { + // Prevents maliciously crafted packets from bypassing our custom book validation. + compound.removeTag("resolved"); + } + } + + @Inject(method = "processCustomPayload", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/item/ItemWrittenBook;validBookTagContents(Lnet/minecraft/nbt/NBTTagCompound;)Z" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void onValidBookTagContents(CPacketCustomPayload packet, CallbackInfo callbackInfo, + String channelName, PacketBuffer packetBuffer, ItemStack itemStack) { + NBTTagCompound compound = itemStack.getTagCompound(); + if (compound != null) { + // Prevents maliciously crafted packets from bypassing our custom book validation. + compound.removeTag("resolved"); + } + } +} \ No newline at end of file diff --git a/src/main/resources/mixins.sledgehammer.core.json b/src/main/resources/mixins.sledgehammer.core.json index c660cf1..0d0abdf 100644 --- a/src/main/resources/mixins.sledgehammer.core.json +++ b/src/main/resources/mixins.sledgehammer.core.json @@ -12,6 +12,8 @@ "block.MixinBlockIce", "entity.MixinEntity_Teleport", "item.MixinItemStack_Exploit", + "item.MixinItemWritableBook", + "network.MixinNetHandlerPlayServer_Book", "network.MixinNetHandlerPlayServer_Event", "network.MixinNetworkManager", "network.MixinNetworkSystem",