Skip to content

Commit 3b4e1e6

Browse files
authored
eval: add bounds checking in LwcMessages.parseTags (#1969)
Validate the requested tag count when decoding Datapoints in LwcMessages.parseTags to ensure it does not exceed maxTags or contain negative values, preventing excessive memory allocations on malformed payloads.
1 parent 17c3f5c commit 3b4e1e6

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

atlas-eval/src/main/scala/com/netflix/atlas/eval/model/LwcMessages.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ import tools.jackson.databind.node.NullNode
3535
*/
3636
object LwcMessages {
3737

38+
// Maximum number of tags allowed when parsing. This is used as a sanity
39+
// check in case a bad payload comes in with a really large size that
40+
// could exhaust memory.
41+
private final val maxTags = 100_000
42+
3843
// For reading arbitrary json structures for events
3944
private val mapper = Json.newMapperBuilder
4045
.disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
@@ -408,6 +413,10 @@ object LwcMessages {
408413
private def parseTags(parser: JsonParser, n: Int): Map[String, String] = {
409414
if (n == 0) {
410415
SortedTagMap.empty
416+
} else if (n < 0 || n > maxTags) {
417+
throw new IllegalArgumentException(
418+
s"requested tag count is invalid or exceeds limit ($n, max: $maxTags)"
419+
)
411420
} else {
412421
val data = new Array[String](2 * n)
413422
var i = 0

atlas-eval/src/test/scala/com/netflix/atlas/eval/model/LwcMessagesSuite.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.netflix.atlas.eval.model
1717

18+
import java.io.ByteArrayOutputStream
1819
import java.util.Random
1920
import java.util.UUID
2021
import scala.util.Using
@@ -324,4 +325,42 @@ class LwcMessagesSuite extends FunSuite {
324325
}
325326

326327
private def randomString: String = UUID.randomUUID().toString
328+
329+
test("batch: invalid tag count throws IllegalArgumentException") {
330+
val baos = new ByteArrayOutputStream()
331+
val gen = Json.newSmileGenerator(baos)
332+
try {
333+
gen.writeStartArray()
334+
gen.writeNumber(2) // Datapoint
335+
gen.writeNumber(1234567890L)
336+
gen.writeString("id")
337+
gen.writeNumber(100_001)
338+
gen.writeNumber(1.0)
339+
gen.writeEndArray()
340+
} finally {
341+
gen.close()
342+
}
343+
intercept[IllegalArgumentException] {
344+
LwcMessages.parseBatch(ByteString.fromArrayUnsafe(baos.toByteArray))
345+
}
346+
}
347+
348+
test("batch: negative tag count throws IllegalArgumentException") {
349+
val baos = new ByteArrayOutputStream()
350+
val gen = Json.newSmileGenerator(baos)
351+
try {
352+
gen.writeStartArray()
353+
gen.writeNumber(2) // Datapoint
354+
gen.writeNumber(1234567890L)
355+
gen.writeString("id")
356+
gen.writeNumber(-1)
357+
gen.writeNumber(1.0)
358+
gen.writeEndArray()
359+
} finally {
360+
gen.close()
361+
}
362+
intercept[IllegalArgumentException] {
363+
LwcMessages.parseBatch(ByteString.fromArrayUnsafe(baos.toByteArray))
364+
}
365+
}
327366
}

0 commit comments

Comments
 (0)