Grief Prevention

Grief Prevention

1M Downloads

Integer overflow in required claimblock calculation when using /claim

smallclock12 opened this issue · 9 comments

commented

Observed Behavior

When specifying a radius greater than 23170 the amount of claim blocks required overflows and starts going down.

Some notable numbers are 46340 which only requires 166k claim blocks to create a 92k x 92k claim, 258015 for only ~20k claim blocks and 1047551 for only 6k. I haven't been able to process these larger numbers.

Running these commands can cause out of memory exceptions or if the server is able to process it, it will be unresponsive while doing so. /claim 46340 took about 60 seconds to process for my server.

I haven't been able to test this in a more real world scenario with claims to collide with and smaller world borders there's a good chance these stop the processing early.

Screenshot from 2024-10-06 23-11-48

Expected Behavior

No overflow, no processing crazy claim sizes for very few claim blocks

Reproduction steps

  1. /claim 23170 and then /claim 23171 to see the required claimblocks reducing
  2. /claim 46340 with 170k claim blocks, will either cause a heap exception or if the server can process it, it will result in a 92k x 92k claim for -166k claimblocks (note the minus)

Stack trace or error log

[21:50:49 INFO]: eepykanna issued server command: /claim 46340
[21:50:59 ERROR]: --- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH  - 1.20.6-150-e61b73f (MC: 1.20.6) ---
[21:50:59 ERROR]: The server has not responded for 10 seconds! Creating thread dump
[21:50:59 ERROR]: ------------------------------
[21:50:59 ERROR]: Server thread dump (Look for plugins here before reporting to Paper!):
[21:50:59 ERROR]: ------------------------------
[21:50:59 ERROR]: Current Thread: Server thread
[21:50:59 ERROR]: 	PID: 62 | Suspended: false | Native: false | State: RUNNABLE
[21:50:59 ERROR]: 	Stack:
[21:50:59 ERROR]: 		[email protected]/java.util.concurrent.ConcurrentHashMap$TreeBin.balanceInsertion(Unknown Source)
[21:50:59 ERROR]: 		[email protected]/java.util.concurrent.ConcurrentHashMap$TreeBin.putTreeVal(Unknown Source)
[21:50:59 ERROR]: 		[email protected]/java.util.concurrent.ConcurrentHashMap.putVal(Unknown Source)
[21:50:59 ERROR]: 		[email protected]/java.util.concurrent.ConcurrentHashMap.put(Unknown Source)
[21:50:59 ERROR]: 		GriefPrevention.jar//me.ryanhamshire.GriefPrevention.DataStore.addToChunkClaimMap(DataStore.java:498)
[21:50:59 ERROR]: 		GriefPrevention.jar//me.ryanhamshire.GriefPrevention.DataStore.addClaim(DataStore.java:469)
[21:50:59 ERROR]: 		GriefPrevention.jar//me.ryanhamshire.GriefPrevention.DataStore.createClaim(DataStore.java:1013)
[21:50:59 ERROR]: 		GriefPrevention.jar//me.ryanhamshire.GriefPrevention.DataStore.createClaim(DataStore.java:863)
[21:50:59 ERROR]: 		GriefPrevention.jar//me.ryanhamshire.GriefPrevention.GriefPrevention.onCommand(GriefPrevention.java:1117)
[21:50:59 ERROR]: 		org.bukkit.command.PluginCommand.execute(PluginCommand.java:45)
[21:50:59 ERROR]: 		io.papermc.paper.command.brigadier.bukkit.BukkitCommandNode$BukkitBrigCommand.run(BukkitCommandNode.java:91)
[21:50:59 ERROR]: 		com.mojang.brigadier.context.ContextChain.runExecutable(ContextChain.java:73)
[21:50:59 ERROR]: 		net.minecraft.commands.execution.tasks.ExecuteCommand.execute(ExecuteCommand.java:31)
[21:50:59 ERROR]: 		net.minecraft.commands.execution.tasks.ExecuteCommand.execute(ExecuteCommand.java:19)
[21:50:59 ERROR]: 		net.minecraft.commands.execution.UnboundEntryAction.lambda$bind$0(UnboundEntryAction.java:8)
[21:50:59 ERROR]: 		net.minecraft.commands.execution.UnboundEntryAction$$Lambda/0x000073ffad3f23f8.execute(Unknown Source)
[21:50:59 ERROR]: 		net.minecraft.commands.execution.CommandQueueEntry.execute(CommandQueueEntry.java:5)
[21:50:59 ERROR]: 		net.minecraft.commands.execution.ExecutionContext.runCommandQueue(ExecutionContext.java:103)
[21:50:59 ERROR]: 		net.minecraft.commands.Commands.executeCommandInContext(Commands.java:448)
[21:50:59 ERROR]: 		net.minecraft.commands.Commands.performCommand(Commands.java:355)
[21:50:59 ERROR]: 		net.minecraft.commands.Commands.performCommand(Commands.java:342)
[21:50:59 ERROR]: 		net.minecraft.commands.Commands.performCommand(Commands.java:337)
[21:50:59 ERROR]: 		net.minecraft.server.network.ServerGamePacketListenerImpl.performUnsignedChatCommand(ServerGamePacketListenerImpl.java:2200)
[21:50:59 ERROR]: 		net.minecraft.server.network.ServerGamePacketListenerImpl.lambda$handleChatCommand$11(ServerGamePacketListenerImpl.java:2174)
[21:50:59 ERROR]: 		net.minecraft.server.network.ServerGamePacketListenerImpl$$Lambda/0x000073ffad3ef1f0.run(Unknown Source)
[21:50:59 ERROR]: 		net.minecraft.server.TickTask.run(TickTask.java:18)
[21:50:59 ERROR]: 		net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:151)
[21:50:59 ERROR]: 		net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:24)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:1511)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:195)
[21:50:59 ERROR]: 		net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:125)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:1488)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:1411)
[21:50:59 ERROR]: 		net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:135)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:1377)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1238)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:323)
[21:50:59 ERROR]: 		net.minecraft.server.MinecraftServer$$Lambda/0x000073ffacbf8968.run(Unknown Source)
[21:50:59 ERROR]: 		[email protected]/java.lang.Thread.runWith(Unknown Source)
[21:50:59 ERROR]: 		[email protected]/java.lang.Thread.run(Unknown Source)

Server version

> version
This server is running Paper version 1.20.6-150-ver/1.20.6@e61b73f (2024-09-16T19:18:19Z) (Implementing API version 1.20.6-R0.1-SNAPSHOT)
You are running the latest version

GriefPrevention version

> version GriefPrevention
GriefPrevention version 16.18.4

Configuration

# Default values are perfect for most servers.  If you want to customize and have a question, look for the answer here first: http://dev.bukkit.org/bukkit-plugins/grief-prevention/pages/setup-and-configuration/

GriefPrevention:
  SeaLevelOverrides:
    world: -1
    world_nether: -1
    world_the_end: -1
  Claims:
    Mode:
      world_nether: Disabled
      world: Survival
      world_the_end: Disabled
    PreventGlobalMonsterEggs: true
    PreventTheft: true
    ProtectCreatures: true
    PreventButtonsSwitches: true
    LockWoodenDoors: false
    LockTrapDoors: false
    LockFenceGates: true
    EnderPearlsRequireAccessTrust: true
    RaidTriggersRequireBuildTrust: true
    ProtectHorses: true
    ProtectDonkeys: true
    ProtectLlamas: true
    InitialBlocks: 100
    Claim Blocks Accrued Per Hour:
      Default: 100
    Max Accrued Claim Blocks:
      Default: 80000
    Accrued Idle Threshold: 0
    AccruedIdlePercent: 0
    AbandonReturnRatio: 1.0
    AutomaticNewPlayerClaimsRadius: 4
    AutomaticNewPlayerClaimsRadiusMinimum: 0
    ExtendIntoGroundDistance: 5
    MinimumWidth: 5
    MinimumArea: 100
    MaximumDepth: -2147483648
    InvestigationTool: STICK
    ModificationTool: GOLDEN_SHOVEL
    Expiration:
      ChestClaimDays: 7
      UnusedClaimDays: 14
      AllClaims:
        DaysInactive: 60
        ExceptWhenOwnerHasTotalClaimBlocks: 10000
        ExceptWhenOwnerHasBonusClaimBlocks: 5000
      AutomaticNatureRestoration:
        SurvivalWorlds: false
    AllowTrappedInAdminClaims: false
    MaximumNumberOfClaimsPerPlayer: 0
    CreationRequiresWorldGuardBuildPermission: true
    VillagerTradingRequiresPermission: true
    CommandsRequiringAccessTrust: /sethome
    DeliverManuals: true
    ManualDeliveryDelaySeconds: 30
    RavagersBreakBlocks: true
    FireSpreadsInClaims: false
    FireDamagesInClaims: false
    LecternReadingRequiresAccessTrust: true
  Spam:
    Enabled: true
    LoginCooldownSeconds: 60
    LoginLogoutNotificationsPerMinute: 5
    ChatSlashCommands: /me;/global;/local
    WhisperSlashCommands: /tell;/pm;/r;/whisper;/msg
    WarningMessage: Please reduce your noise level.  Spammers will be banned.
    BanOffenders: true
    BanMessage: Banned for spam.
    AllowedIpAddresses: 1.2.3.4; 5.6.7.8
    DeathMessageCooldownSeconds: 120
    Logout Message Delay In Seconds: 0
  PvP:
    RulesEnabledInWorld:
      world: true
      world_nether: true
      world_the_end: true
    ProtectFreshSpawns: true
    PunishLogout: true
    CombatTimeoutSeconds: 15
    AllowCombatItemDrop: false
    BlockedSlashCommands: /home;/vanish;/spawn;/tpa
    ProtectPlayersInLandClaims:
      PlayerOwnedClaims: true
      AdministrativeClaims: true
      AdministrativeSubdivisions: true
    AllowLavaDumpingNearOtherPlayers:
      PvPWorlds: true
      NonPvPWorlds: false
    AllowFlintAndSteelNearOtherPlayers:
      PvPWorlds: true
      NonPvPWorlds: false
    ProtectPetsOutsideLandClaims: false
  Economy:
    ClaimBlocksMaxBonus: 0
    ClaimBlocksPurchaseCost: 0.0
    ClaimBlocksSellValue: 0.0
  ProtectItemsDroppedOnDeath:
    PvPWorlds: false
    NonPvPWorlds: true
  BlockLandClaimExplosions: true
  BlockSurfaceCreeperExplosions: true
  BlockSurfaceOtherExplosions: true
  LimitSkyTrees: true
  LimitTreeGrowth: false
  PistonMovement: CLAIMS_ONLY
  PistonExplosionSound: true
  FireSpreads: false
  FireDestroys: false
  AdminsGetWhispers: true
  AdminsGetSignNotifications: true
  VisualizationAntiCheatCompatMode: false
  SmartBan: true
  Mute New Players Using Banned Words: true
  MaxPlayersPerIpAddress: 3
  SilenceBans: true
  Siege:
    Worlds: []
    BreakableBlocks:
    - PINK_WOOL
    - LIGHT_GRAY_WOOL
    - BLACK_WOOL
    - PURPLE_WOOL
    - LIME_WOOL
    - MAGENTA_WOOL
    - BLUE_WOOL
    - GLASS
    - SPRUCE_PLANKS
    - DEAD_BUSH
    - WHITE_WOOL
    - GRAY_WOOL
    - OAK_PLANKS
    - GLASS_PANE
    - CYAN_WOOL
    - GREEN_WOOL
    - FERN
    - BIRCH_PLANKS
    - RED_WOOL
    - DARK_OAK_PLANKS
    - SAND
    - COBBLESTONE
    - ACACIA_PLANKS
    - SHORT_GRASS
    - GRAVEL
    - BROWN_WOOL
    - SNOW
    - YELLOW_WOOL
    - LIGHT_BLUE_WOOL
    - JUNGLE_PLANKS
    - ORANGE_WOOL
    - DIRT
    - GRASS_BLOCK
    DoorsOpenDelayInSeconds: 300
    CooldownEndInMinutes: 60
  EndermenMoveBlocks: false
  SilverfishBreakBlocks: false
  CreaturesTrampleCrops: false
  RabbitsEatCrops: true
  HardModeZombiesBreakDoors: false
  MobProjectilesChangeBlocks: false
  Database:
    URL: ''
    UserName: ''
    Password: ''
  UseBanCommand: false
  BanCommandPattern: ban %name% %reason%
  Advanced:
    fixNegativeClaimblockAmounts: true
    ClaimExpirationCheckRate: 60
    OfflinePlayer_cache_days: 90
  Abridged Logs:
    Days To Keep: 7
    Included Entry Types:
      Social Activity: true
      Suspicious Activity: true
      Administrative Activity: false
      Debug: false
      Muted Chat Messages: false
  ConfigVersion: 1

Plugin list

> plugins
Server Plugins (1):
§xBukkit Plugins:
 - GriefPrevention

Running without GriefPrevention

  • I attempted running the server without GriefPrevention installed.
  • The problem does not occur when GriefPrevention is removed from the server.

Running with only GriefPrevention

  • I attempted running only GriefPrevention on the server.
  • The issue still occurs when GriefPrevention is the only plugin running.

Running on a fresh, clean server installation

  • I attempted testing for the issue on a new server.
  • The issue still occurs on a new server.

Using unmodified client

  • I attempted testing for the issue with the vanilla client.
  • The issue still occurs when using the vanilla client.

We appreciate you taking the time to fill out a bug report!

  • I searched for similar issues before submitting this bug report.
commented

I don't disagree with the priority, it seems once another claim or the world border gets in the way it doesn't get to the addToChunkClaimMap function which is where the performance takes a big hit (which is what that PR seems to address).

we don't find it reasonable for any player to have the claimblocks to create such a large claim.

I do just want to re-iterate incase it was missed, you only need ~6000 claim blocks to run /claim 1047551 so you really don't need many claimblocks to try and run it.

commented

I thought we had limited /claim and /extendclaim to 1000 blocks, but that code clearly isn't in place, so I'm wondering if that was a discussion we had somewhere and never implemented. Either way, an easy enough safeguard to put in place, though eventually we should do more to prevent edge cases causing values to wrap.

commented

I think part of this is to be addressed with #2295 which will likely be addressed in v18 when we do some more major changes/removals. In general, the priority for this is low as we don't find it reasonable for any player to have the claimblocks to create such a large claim.

commented

I thought we had limited /claim and /extendclaim to 1000 blocks

Never heard of this limitation ever at all.

I do just want to re-iterate incase it was missed, you only need ~6000 claim blocks to run /claim 1047551 so you really don't need many claimblocks to try and run it.

Ah, I was thinking then of issues with very skinny, long claims.

commented

Never heard of this limitation ever at all.

Managed to find what I was thinking of - it was a single bullet point in a post I'd made after a couple of paragraphs about problems in this vein, only mentioned /extendclaim, and didn't specify an amount. Explains why it was in my head, it was one of my ideas but we ended up going a different route to handle that particular overflow issue.

Since it's come up again, how do we feel about a limit of 1000? Maybe only have it apply to people not in ignore claims mode, or maybe 5000/10000 would be more appropriate to keep supporting niche admin usage? It would be pretty simple to apply to legacy, and we can work on a more addon-interference-proof solution (like totaling claim amounts into a long and using safe math ops) for future versions.

commented

idk what most people do, but I suppose 1k is an ok limit.

commented

I think 1000 is a pretty low limit. If i have a 100x100 claim, expanding 11 blocks already breaks the 1000 limit, unless we're referring to limiting the command input argument to1000 blocks, which seems ok to me. (Should this limit be a config option?)

As for admins who have access to /ignoreclaims, we could just have a confirmation message similarly to how there's a confirmation message when abandoning all claims

"Are you sure you want to expand 100000 blocks? Expanding such a high amount can cause errors that can lead to a server crash. If so, type /extendclaim 100000 confirm" (or something similar)

commented

I think the limit is for the input argument afaik, yea.

I'm ok with a config option in legacy, in the Advanced section. But not so for master (or rather, as jikoo mentioned, a proper fix for master).

As for a warning message, if it's low maintenance sure, but given that a proper fix would be in master, I don't see a huge need for it.

commented

I think 1000 is a pretty low limit. If i have a 100x100 claim, expanding 11 blocks already breaks the 1000 limit, unless we're referring to limiting the command input argument to1000 blocks, which seems ok to me. (Should this limit be a config option?)

Just a cap on the parameter which is block distance in one dimension, not on area. Personally no need for config as long as we leave it high enough, players are unlikely to have enough blocks to make expanding area at those rates a regular thing. /claim 1000 would create a 2000x2000 claim, which is 4m claim blocks.

I like the idea of a confirmation on bypass because GP really can't handle claims of that size well right now.