Folia: Cause.Builder reads Creature#getTarget() from a non-owning region during vehicle damage
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 72/100
Hướng nghiên cứu
Start in Cause.java at Cause.Builder.addAll(...), then trace the call from EventAbstractionListener.onVehicleDamage. Use the deterministic event harness described in the report to reproduce the cross-region access. Done means cause construction preserves the projectile and shooter, avoids remote mutable-state reads, and lets the vehicle protection check complete normally.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
WorldEdit Version
WorldEdit 7.4.3+7515-78babeb
WorldGuard Version
WorldGuard 7.0.17+2370-e42d8bc
Platform Version
- Official Folia
1.21.11-14-ver/1.21.11@529aabc - Minecraft
1.21.11 - Java
25.0.3 - Four Folia region tick threads
The Folia server JAR was downloaded from PaperMC's official download service.
Confirmations
- I am using the most recent Minecraft release.
- I am using a version of WorldEdit compatible with my Minecraft version.
- I am using a version of WorldGuard compatible with my Minecraft version.
- I am using the latest or recommended version of my platform software.
- I am NOT using a hybrid server, e.g. a server that combines Bukkit and Forge.
- I am NOT using a fork of WorldEdit, such as FastAsyncWorldEdit or AsyncWorldEdit.
Bug Description
When a projectile has a Creature shooter owned by a different Folia region, WorldGuard reads the shooter's mutable AI state from the projectile or vehicle region thread while building the event cause chain.
The problem is in Cause.Builder.addAll(...). After following Projectile#getShooter(), WorldGuard reaches the remote Creature and unconditionally calls Creature#getTarget(). Folia correctly rejects this read because the current region does not own the creature.
This was reproduced on an isolated official Folia server. Immediately before firing VehicleDamageEvent, the ownership checks returned:
Bukkit.isOwnedByCurrentRegion(arrow) = true
Bukkit.isOwnedByCurrentRegion(pillager) = false
WorldGuard then produced this call path:
Thread failed main thread check: Accessing entity state off owning region's thread
at ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(TickThread.java:97)
at org.bukkit.craftbukkit.entity.CraftPillager.getHandle(CraftPillager.java:16)
at org.bukkit.craftbukkit.entity.CraftMob.getTarget(CraftMob.java:71)
at com.sk89q.worldguard.bukkit.cause.Cause$Builder.addAll(Cause.java:336)
at com.sk89q.worldguard.bukkit.cause.Cause$Builder.addAll(Cause.java:298)
at com.sk89q.worldguard.bukkit.cause.Cause.create(Cause.java:226)
at com.sk89q.worldguard.bukkit.listener.EventAbstractionListener.onVehicleDamage(EventAbstractionListener.java:1005)
The exception aborts the WorldGuard listener before it completes its protection check. The VehicleDamageEvent returns without being cancelled, so a protected vehicle may remain vulnerable.
Expected Behavior
WorldGuard should keep the projectile and its shooter in the cause chain without reading mutable state from an entity owned by another Folia region.
If the current region owns the creature, WorldGuard may continue resolving getTarget() and getIgniter(). If it does not own the creature, WorldGuard should skip only that recursive AI-state expansion and continue processing the event normally.
Reproduction Steps
- Start official Folia
1.21.11-14(529aabc) with four region tick threads and Java 25. - Install WorldEdit
7.4.3+7515-78babeband WorldGuard7.0.17+2370-e42d8bc. - In region A near
x=0, create a persistent pillager. - Create an arrow in region A and assign the pillager as its shooter.
- Move the arrow to region B near
x=16384withteleportAsync(...), leaving the pillager in region A. - On the arrow's entity scheduler in region B, create a minecart and fire a real Bukkit
VehicleDamageEventwith the arrow as the attacker. - Confirm that
Bukkit.isOwnedByCurrentRegion(arrow)istrueandBukkit.isOwnedByCurrentRegion(pillager)isfalseon the event thread. - Observe WorldGuard calling
CraftMob#getTarget()throughCause.Builder.addAll(...)and Folia rejecting the cross-region entity-state read.
The test uses a deterministic event harness to isolate WorldGuard's listener. It does not modify WorldGuard or Folia internals.
Optional WorldGuard-Report
Not applicable. This failure occurs while WorldGuard constructs the event cause, before a region-specific protection result can be completed.
Anything Else?
The relevant WorldGuard logic currently reads creature state recursively without checking Folia ownership:
} else if (o instanceof Creeper creeper) {
indirect = true;
addAll(creeper.getTarget(), creeper.getIgniter());
} else if (o instanceof Creature creature) {
indirect = true;
addAll(creature.getTarget());
}
A possible fix is to preserve the creature as a cause but guard only the mutable target and igniter lookups:
} else if (o instanceof Creeper creeper) {
indirect = true;
if (!WorldGuardPlugin.inst().isFolia()
|| Bukkit.isOwnedByCurrentRegion(creeper)) {
addAll(creeper.getTarget(), creeper.getIgniter());
}
} else if (o instanceof Creature creature) {
indirect = true;
if (!WorldGuardPlugin.inst().isFolia()
|| Bukkit.isOwnedByCurrentRegion(creature)) {
addAll(creature.getTarget());
}
}
Bukkit.isOwnedByCurrentRegion(Entity) is suitable here because it checks ownership without first reading the remote entity's location or other owner-only state.
Moving cause construction to the shooter's scheduler is not a safe replacement: vehicle-event cancellation must finish synchronously on the vehicle's owning region, and blocking one region while waiting for another can introduce deadlocks or tick latency.
- Ngôn ngữ chính
- Java
- Star
- 939
- Fork
- 672
- Merge trung bình
- 22 giờ 57 phút
- Pull request đã merge (30 ngày)
- 1
Chuẩn bị môi trường
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của EngineHub/WorldGuard
-
status:pending type:bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
EngineHub/WorldGuard#2305 ·
-
status:pending type:bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
EngineHub/WorldGuard#2302 · 4 bình luận ·
-
status:pending type:feature-request
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
EngineHub/WorldGuard#2301 · 5 bình luận ·
-
Audio and visual accompanimentĐang mởstatus:pending type:feature-request
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
EngineHub/WorldGuard#2288 · 1 bình luận ·
-
status:pending type:feature-request
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
EngineHub/WorldGuard#2287 ·
Tất cả issue của EngineHub/WorldGuard
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
redhat-developer/intellij-quarkus#1626 ·
-
Type/Bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
wso2/product-integrator-mi#5061 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
quarkiverse/quarkus-roq#1277 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Typos in page footerĐang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
apache/logging-site#48 ·
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
apache/maven-surefire#3496 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày