Skip to content

Commit

Permalink
chore(model): Reject reading multiple YAML documents per file
Browse files Browse the repository at this point in the history
Resolves #6873.

Signed-off-by: Sebastian Schuberth <sebastian@doubleopen.org>
  • Loading branch information
sschuberth committed Jun 11, 2024
1 parent 7953965 commit 64fccd8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
18 changes: 15 additions & 3 deletions model/src/main/kotlin/FileFormat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ package org.ossreviewtoolkit.model
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.convertValue
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.readValues

import java.io.File
import java.io.IOException

import org.ossreviewtoolkit.utils.common.safeMkdirs

Expand Down Expand Up @@ -94,9 +95,20 @@ fun File.mapper() = FileFormat.forFile(this).mapper
fun File.readTree(): JsonNode = mapper().readTree(this)

/**
* Use the Jackson mapper returned from [File.mapper] to read an object of type [T] from this file.
* Use the Jackson mapper returned from [File.mapper] to read a single object of type [T] from this file. Throw an
* [IOException] if not exactly one value is contained in the file, e.g. in case of multiple YAML documents per file.
*/
inline fun <reified T : Any> File.readValue(): T = mapper().readValue(this)
inline fun <reified T : Any> File.readValue(): T {
val mapper = mapper()
val parser = mapper.factory.createParser(this)

val values = mapper.readValues<T>(parser).readAll().also {
if (it.isEmpty()) throw IOException("No object found in file '$this'.")
if (it.size > 1) throw IOException("Multiple top-level objects found in file '$this'.")
}

return values.first()
}

/**
* Use the Jackson mapper returned from [File.mapper] to read an object of type [T] from this file, or return null if
Expand Down
23 changes: 23 additions & 0 deletions model/src/test/kotlin/FileFormatTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package org.ossreviewtoolkit.model
import com.fasterxml.jackson.core.JsonParseException

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.assertions.throwables.shouldThrowWithMessage
import io.kotest.core.spec.style.WordSpec
import io.kotest.engine.spec.tempfile
import io.kotest.matchers.file.shouldHaveFileSize
Expand Down Expand Up @@ -58,6 +59,28 @@ class FileFormatTest : WordSpec({
file.readValue()
}
}

"refuse to read multiple documents per file" {
val file = tempfile(null, ".yml").apply {
@Suppress("MaxLineLength")
writeText(
"""
---
id: "Maven:dom4j:dom4j:1.6.1"
source_artifact_url: "https://repo.maven.apache.org/maven2/dom4j/dom4j/1.6.1/dom4j-1.6.1-sources.jar"
---
id: "Maven:dom4j:dom4j:1.6.1"
source_artifact_url: "<INTERNAL_ARTIFACTORY>/dom4j-1.6.1-sources.jar"
""".trimIndent()
)
}

shouldThrowWithMessage<IOException>(
"Multiple top-level objects found in file '$file'."
) {
file.readValue()
}
}
}

"File.readValueOrNull()" should {
Expand Down

0 comments on commit 64fccd8

Please sign in to comment.