Skip to content
Permalink
Browse files

Fix broken normalizeAndRelativize, add documentation

  • Loading branch information...
cy6erGn0m committed Oct 12, 2018
1 parent 3b2262a commit 98aab9f4ea94d1be5fc79bad0ed642823c2716f3
@@ -50,11 +50,8 @@ class StaticContentTest {
assertEquals(HttpStatusCode.OK, result.response.status())
}
// can't get up to containing folder
assertFailsWith<InvalidPathException> {
handleRequest(HttpMethod.Get, "/selected/../features/StaticContentTest.kt").let { result ->
assertTrue(result.requestHandled)
assertEquals(HttpStatusCode.OK, result.response.status())
}
handleRequest(HttpMethod.Get, "/selected/../features/StaticContentTest.kt").let { result ->
assertFalse(result.requestHandled)
}

// can serve select file from other dir
@@ -138,11 +135,9 @@ class StaticContentTest {
}
}

listOf("../pom.xml", "../../pom.xml", "/../pom.xml", "/../../pom.xml", "/./.././../pom.xml").forEach { path ->
assertFailsWith<InvalidPathException> {
handleRequest(HttpMethod.Get, path).let { result ->
assertFalse(result.requestHandled, "Should be unhandled for path $path")
}
listOf("../build.gradle", "../../build.gradle", "/../build.gradle", "/../../build.gradle", "/./.././../build.gradle").forEach { path ->
handleRequest(HttpMethod.Get, path).let { result ->
assertFalse(result.requestHandled, "Should be unhandled for path $path")
}
}
}
@@ -180,13 +175,13 @@ class StaticContentTest {
call.respond(LocalFileContent(basedir, "../../../../../../../../../../../../../etc/passwd"))
}
assertFailsWithSuspended<Exception> {
call.respond(LocalFileContent(basedir.toPath(), Paths.get("../pom.xml")))
call.respond(LocalFileContent(basedir.toPath(), Paths.get("../build.gradle")))
}
assertFailsWithSuspended<Exception> {
call.respond(LocalFileContent(basedir.toPath(), Paths.get("../../pom.xml")))
call.respond(LocalFileContent(basedir.toPath(), Paths.get("../../build.gradle")))
}
assertFailsWithSuspended<Exception> {
call.respond(LocalFileContent(basedir.toPath(), Paths.get("/../pom.xml")))
call.respond(LocalFileContent(basedir.toPath(), Paths.get("/../build.gradle")))
}
}

@@ -205,13 +200,13 @@ class StaticContentTest {
call.respond(LocalFileContent(basedir.toPath(), Paths.get("../../../../../../../../../../../../../etc/passwd")))
}
assertFailsWithSuspended<Exception> {
call.respond(LocalFileContent(basedir, "../pom.xml"))
call.respond(LocalFileContent(basedir, "../build.gradle"))
}
assertFailsWithSuspended<Exception> {
call.respond(LocalFileContent(basedir, "../../pom.xml"))
call.respond(LocalFileContent(basedir, "../../build.gradle"))
}
assertFailsWithSuspended<Exception> {
call.respond(LocalFileContent(basedir, "/../pom.xml"))
call.respond(LocalFileContent(basedir, "/../build.gradle"))
}
}

@@ -8,10 +8,20 @@ import java.nio.file.*
*
* Extension is a substring of a [Path.fileName] after last dot
*/
val Path.extension get() = fileName.toString().substringAfterLast(".")
val Path.extension: String get() = fileName.toString().substringAfterLast(".")

/**
* Append a [relativePath] safely that means that adding any extra `..` path elements will not let
* access anything out of the reference directory (unless you have symbolic or hard links or multiple mount points)
*/
@KtorExperimentalAPI
fun File.combineSafe(relativePath: String): File = combineSafe(Paths.get(relativePath))

/**
* Append a [relativePath] safely that means that adding any extra `..` path elements will not let
* access anything out of the reference directory (unless you have symbolic or hard links or multiple mount points)
*/
@KtorExperimentalAPI
fun File.combineSafe(relativePath: Path): File {
val normalized = relativePath.normalizeAndRelativize()
if (normalized.startsWith("..")) {
@@ -22,6 +32,11 @@ fun File.combineSafe(relativePath: Path): File {
return File(this, normalized.toString())
}

/**
* Append a [relativePath] safely that means that adding any extra `..` path elements will not let
* access anything out of the reference directory (unless you have symbolic or hard links or multiple mount points)
*/
@KtorExperimentalAPI
fun Path.combineSafe(relativePath: Path): File {
val normalized = relativePath.normalizeAndRelativize()
if (normalized.startsWith("..")) {
@@ -32,12 +47,15 @@ fun Path.combineSafe(relativePath: Path): File {
return resolve(normalized).toFile()
}

/**
* Remove all redundant `.` and `..` path elements. Leading `..` are also considered redundant.
*/
@KtorExperimentalAPI
fun Path.normalizeAndRelativize(): Path =
root?.relativize(this)?.normalize()?.dropLeadingTopDirs() ?: normalize().dropLeadingTopDirs()

private fun Path.dropLeadingTopDirs(): Path {
return this
val startIndex = indexOfFirst { it.toString() != ".." }
if (startIndex == 0) return this
return subpath(startIndex, nameCount)
}
}

0 comments on commit 98aab9f

Please sign in to comment.
You can’t perform that action at this time.