From abaa347ad4856b209c741a8b29884d14a54c4b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= <43724816+Aurelien30000@users.noreply.github.com> Date: Sat, 7 Aug 2021 11:09:33 +0200 Subject: [PATCH] Fix major security bugs (3 brushes + superpickaxe)! (#1213) * Fix major security bugs (3 brushes + superpickaxe)! - Due to some recent changes, FAWE could edit everything in the world, no matter other plugin protections such as PS or WG. - Fix superpickaxe allow to bypass protections => Fix SurvivalModeExtent not taking into account protections plugins due to breaking blocks naturally to get drops. * Adress requests - Revert some unsuitabe changes - Add FAWE diff comments * Clean imports * Adress requests Co-authored-by: NotMyFault --- .../sk89q/worldedit/bukkit/BukkitWorld.java | 10 ++++++++ .../core/wrappers/WorldWrapper.java | 8 +++++++ .../command/tool/BlockDataCyler.java | 2 -- .../worldedit/command/tool/BlockReplacer.java | 1 - .../worldedit/command/tool/SinglePickaxe.java | 13 +++++++---- .../worldedit/command/tool/StackTool.java | 1 - .../extent/world/SurvivalModeExtent.java | 23 +++++++++++++++++-- .../java/com/sk89q/worldedit/world/World.java | 14 +++++++++++ 8 files changed, 61 insertions(+), 11 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index dd4acc769..ccef98676 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -67,12 +67,14 @@ import org.bukkit.inventory.InventoryHolder; import java.lang.ref.WeakReference; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; @@ -470,6 +472,14 @@ public class BukkitWorld extends AbstractWorld { getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally(); } + //FAWE start + @Override + public Collection getBlockDrops(BlockVector3 position) { + return getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()).getDrops().stream() + .map(BukkitAdapter::adapt).collect(Collectors.toList()); + } + //FAWE end + @Override public boolean canPlaceAt(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState blockState) { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java index 1499a94ac..d3c5960bd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java @@ -39,6 +39,7 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.weather.WeatherType; import javax.annotation.Nullable; +import java.util.Collection; import java.util.List; import java.util.Set; @@ -240,6 +241,13 @@ public class WorldWrapper extends AbstractWorld { }); } + //FAWE start + @Override + public Collection getBlockDrops(final BlockVector3 position) { + return TaskManager.IMP.sync(() -> parent.getBlockDrops(position)); + } + //FAWE end + @Override public boolean regenerate(Region region, EditSession session) { return parent.regenerate(region, session); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java index c776dc38d..da428c0ad 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java @@ -90,8 +90,6 @@ public class BlockDataCyler implements DoubleActionBlockTool { BlockState newBlock = block.with(objProp, currentProperty.getValues().get(index)); try (EditSession editSession = session.createEditSession(player)) { - editSession.disableBuffering(); - try { editSession.setBlock(blockPoint, newBlock); player.print(Caption.of( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java index 5ee353957..75ef200c6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java @@ -65,7 +65,6 @@ public class BlockReplacer implements DoubleActionBlockTool { try (EditSession editSession = session.createEditSession(player)) { try { - editSession.disableBuffering(); BlockVector3 position = clicked.toVector().toBlockPoint(); editSession.setBlock(position, pattern); } catch (MaxChangedBlocksException ignored) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java index 216ac0042..b35865fb3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java @@ -63,11 +63,14 @@ public class SinglePickaxe implements BlockTool { } try (EditSession editSession = session.createEditSession(player)) { - editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop); - editSession.setBlock(blockPoint, BlockTypes.AIR.getDefaultState()); - session.remember(editSession); - } catch (MaxChangedBlocksException e) { - player.print(Caption.of("worldedit.tool.max-block-changes")); + try { + editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop); + editSession.setBlock(blockPoint, BlockTypes.AIR.getDefaultState()); + } catch (MaxChangedBlocksException e) { + player.print(Caption.of("worldedit.tool.max-block-changes")); + } finally { + session.remember(editSession); + } } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java index aeaeff9b7..614bbcf32 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java @@ -63,7 +63,6 @@ public class StackTool implements BlockTool { BlockStateHolder block = editSession.getFullBlock(clicked.toVector().toBlockPoint()); try { - editSession.disableBuffering(); BlockVector3 position = clicked.toVector().toBlockPoint(); for (int i = 0; i < range; i++) { position = position.add(face.toBlockVector()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java index 2cccc8c45..c061b0b35 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java @@ -19,7 +19,10 @@ package com.sk89q.worldedit.extent.world; +import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; @@ -27,6 +30,8 @@ import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; +import java.util.Collection; + import static com.google.common.base.Preconditions.checkNotNull; /** @@ -91,8 +96,22 @@ public class SurvivalModeExtent extends AbstractDelegateExtent { @Override public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { if (toolUse && block.getBlockType().getMaterial().isAir()) { - world.simulateBlockMine(location); - return true; + Collection drops = world.getBlockDrops(location); + boolean canSet = super.setBlock(location, block); + if (canSet) { + TaskManager.IMP.sync(new RunnableVal<>() { + @Override + public void run(Object value) { + for (BaseItemStack stack : drops) { + world.dropItem(location.toVector3(), stack); + } + } + }); + + return true; + } else { + return false; + } } else { // Can't be an inlined check due to inconsistent generic return type if (stripNbt) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java index 5db1a8e72..b14478dcf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java @@ -50,6 +50,8 @@ import com.sk89q.worldedit.world.weather.WeatherType; import javax.annotation.Nullable; import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; import java.util.Locale; import java.util.Set; @@ -218,6 +220,18 @@ public interface World extends Extent, Keyed, IChunkCache { */ void simulateBlockMine(BlockVector3 position); + //FAWE start + /** + * Return items that may drop by destroying this block. + * + * @param position the position + * @return Block drops + */ + default Collection getBlockDrops(BlockVector3 position) { + return Collections.emptyList(); + } + //FAWE end + /** * Gets whether the given {@link BlockState} can be placed here. *