Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.

Commit ee7f6cc

Browse files
committed
feat: centralize nesting depth validation in PersistentPlayerDataContainerView
- Moved `MAX_NESTING_DEPTH` and related logic to `PersistentPlayerDataContainerView` for consistent enforcement across components. - Updated `PdcOp` and data iteration logic to utilize the centralized validation method.
1 parent 71297ee commit ee7f6cc

File tree

3 files changed

+30
-19
lines changed

3 files changed

+30
-19
lines changed

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/player/ppdc/PersistentPlayerDataContainerView.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,23 @@ interface PersistentPlayerDataContainerView {
8787
fun writeToBuf(buf: SurfByteBuf)
8888

8989
fun snapshot(): PersistentPlayerDataContainerView
90+
91+
companion object {
92+
/**
93+
* Maximum nesting depth for compound tags.
94+
* This limit prevents memory exhaustion from extremely large nested structures.
95+
* Set to a reasonable limit that should handle most legitimate use cases while
96+
* protecting against pathological inputs.
97+
*/
98+
const val MAX_NESTING_DEPTH = 512
99+
100+
inline fun ensureValidNestingDepth(
101+
depth: Int,
102+
exceptionFactory: (message: String) -> Throwable = ::IllegalStateException
103+
) {
104+
if (depth > MAX_NESTING_DEPTH) {
105+
throw exceptionFactory("Exceeded maximum allowed nesting depth of $MAX_NESTING_DEPTH. This likely indicates a corrupted or maliciously crafted data structure.")
106+
}
107+
}
108+
}
90109
}

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/player/ppdc/PersistentPlayerDataContainerViewImpl.kt

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,6 @@ abstract class PersistentPlayerDataContainerViewImpl : PersistentPlayerDataConta
1717
abstract fun toTagCompound(): CompoundBinaryTag
1818
abstract fun getTag(key: String): BinaryTag?
1919

20-
companion object {
21-
/**
22-
* Maximum nesting depth for compound tags during deep copy operations.
23-
* This limit prevents memory exhaustion from extremely large nested structures.
24-
* Set to a reasonable limit that should handle most legitimate use cases while
25-
* protecting against pathological inputs.
26-
*/
27-
private const val MAX_NESTING_DEPTH = 512
28-
}
29-
3020
override fun <P : Any, C> has(
3121
key: Key,
3222
type: PersistentPlayerDataType<P, C>
@@ -177,7 +167,6 @@ abstract class PersistentPlayerDataContainerViewImpl : PersistentPlayerDataConta
177167
return list
178168
}
179169

180-
// Use ArrayDeque for optimal performance in stack-like operations
181170
val stack = ArrayDeque<Frame>()
182171
stack.addLast(
183172
Frame(
@@ -198,14 +187,8 @@ abstract class PersistentPlayerDataContainerViewImpl : PersistentPlayerDataConta
198187
val (key, value) = top.entries[top.idx++]
199188

200189
if (value is CompoundBinaryTag) {
201-
// Check nesting depth to prevent memory exhaustion
202-
if (stack.size >= MAX_NESTING_DEPTH) {
203-
throw IllegalStateException(
204-
"CompoundBinaryTag nesting depth exceeds maximum limit of $MAX_NESTING_DEPTH. " +
205-
"This likely indicates a corrupted or maliciously crafted data structure."
206-
)
207-
}
208-
190+
PersistentPlayerDataContainerView.ensureValidNestingDepth(stack.size)
191+
209192
stack.addLast(top)
210193
stack.addLast(
211194
Frame(

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/player/ppdc/network/PdcOp.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import dev.slne.surf.cloud.api.common.netty.protocol.buffer.readList
66
import dev.slne.surf.cloud.api.common.netty.protocol.buffer.readUtf
77
import dev.slne.surf.cloud.api.common.netty.protocol.buffer.writeCollection
88
import dev.slne.surf.cloud.api.common.netty.protocol.buffer.writeUtf
9+
import dev.slne.surf.cloud.api.common.player.ppdc.PersistentPlayerDataContainerView
910
import dev.slne.surf.cloud.api.common.util.ByIdMap
1011
import io.netty.buffer.ByteBuf
1112
import net.kyori.adventure.nbt.BinaryTag
@@ -19,12 +20,20 @@ sealed interface PdcOp {
1920
val value: BinaryTag
2021
) : PdcOp {
2122
override val type = Type.PUT
23+
24+
init {
25+
PersistentPlayerDataContainerView.ensureValidNestingDepth(path.size)
26+
}
2227
}
2328

2429
data class Remove(
2530
override val path: List<String>
2631
) : PdcOp {
2732
override val type = Type.REMOVE
33+
34+
init {
35+
PersistentPlayerDataContainerView.ensureValidNestingDepth(path.size)
36+
}
2837
}
2938

3039
companion object {

0 commit comments

Comments
 (0)