Skip to content

Commit d2b554e

Browse files
Use os-lib to handle incoming paths (#482)
This is also more secure, ensuring these do not contain '..' parts
1 parent ad41371 commit d2b554e

File tree

2 files changed

+28
-19
lines changed

2 files changed

+28
-19
lines changed

build.sbt

+2-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ lazy val server = project
124124
"org.slf4j" % "slf4j-api" % "2.0.16",
125125
"org.jboss.xnio" % "xnio-nio" % "3.8.0.Final",
126126
"org.scalameta" % "semanticdb-scalac-core" % Version.scalameta cross CrossVersion.full,
127-
("org.scalameta" %% "mtags" % Version.mtags).cross(CrossVersion.full)
127+
("org.scalameta" %% "mtags" % Version.mtags).cross(CrossVersion.full),
128+
"com.lihaoyi" %% "os-lib" % "0.10.1"
128129
),
129130
(Compile / packageBin) := {
130131
import java.io.FileOutputStream

metabrowse-server/src/main/scala/metabrowse/server/MetabrowseServer.scala

+26-18
Original file line numberDiff line numberDiff line change
@@ -232,30 +232,30 @@ class MetabrowseServer(
232232
.build()
233233

234234
private def getBytes(exchange: HttpServerExchange): Array[Byte] = {
235-
val path = exchange.getRequestPath.stripSuffix(".gz")
236-
if (path.endsWith("index.workspace")) {
235+
val path = os.SubPath("." + exchange.getRequestPath.stripSuffix(".gz"))
236+
if (path.lastOpt.exists(_.endsWith("index.workspace"))) {
237237
getWorkspace.toByteArray
238-
} else if (path.endsWith(".symbolindexes")) {
238+
} else if (path.lastOpt.exists(_.endsWith(".symbolindexes"))) {
239239
val header = exchange.getRequestHeaders.get("Metabrowse-Symbol")
240240
if (header.isEmpty) {
241241
logger.error(s"no Metabrowse-Symbol header: $exchange")
242242
Array.emptyByteArray
243243
} else {
244244
getSymbol(header.getFirst).toByteArray
245245
}
246-
} else if (path.endsWith(".semanticdb")) {
246+
} else if (path.lastOpt.exists(_.endsWith(".semanticdb"))) {
247247
getSemanticdb(path).toByteArray
248-
} else if (path.endsWith(".map")) {
248+
} else if (path.lastOpt.exists(_.endsWith(".map"))) {
249249
// Ignore requests for sourcemaps.
250250
Array.emptyByteArray
251251
} else {
252-
val actualPath = if (path == "/") "/index.html" else path
252+
val actualPath = if (path == os.sub) os.sub / "index.html" else path
253253
withInputStream(
254254
Thread
255255
.currentThread()
256256
.getContextClassLoader
257257
.getResourceAsStream(
258-
s"metabrowse/server/assets/${actualPath.stripPrefix("/")}"
258+
(os.sub / "metabrowse" / "server" / "assets" / actualPath).toString
259259
)
260260
) { is =>
261261
if (is == null) {
@@ -301,27 +301,35 @@ class MetabrowseServer(
301301
Workspace(filenames.result().toSeq)
302302
}
303303

304-
private def getSemanticdb(filename: String): TextDocuments = {
305-
val path = filename
306-
.stripPrefix("/semanticdb/")
307-
.stripPrefix("/") // optional '/'
308-
.stripSuffix(".semanticdb")
309-
logger.info(path)
304+
private def getSemanticdb(subPath: os.SubPath): TextDocuments = {
305+
val path = {
306+
val subPath0 =
307+
if (subPath.startsWith(os.sub / "semanticdb"))
308+
subPath.relativeTo(os.sub / "semanticdb").asSubPath
309+
else
310+
subPath
311+
subPath0.lastOpt match {
312+
case Some(name) if name.endsWith(".semanticdb") =>
313+
subPath0 / os.up / name.stripSuffix(".semanticdb")
314+
case _ => subPath0
315+
}
316+
}
317+
logger.info(path.toString)
310318
for {
311-
text <- state.get().source(path).orElse {
319+
text <- state.get().source(path.toString).orElse {
312320
logger.warn(s"no source file: $path")
313321
None
314322
}
315323
doc <- try {
316324
val timeout = TimeUnit.SECONDS.toMillis(10)
317-
val textDocument = if (path.endsWith(".java")) {
318-
val input = Input.VirtualFile(path, text)
325+
val textDocument = if (path.lastOpt.exists(_.endsWith(".java"))) {
326+
val input = Input.VirtualFile(path.toString, text)
319327
t.JavaMtags.index(input, includeMembers = true).index()
320328
} else {
321329
InteractiveSemanticdb.toTextDocument(
322330
global,
323331
text,
324-
filename,
332+
subPath.toString,
325333
timeout,
326334
List(
327335
"-P:semanticdb:synthetics:on",
@@ -332,7 +340,7 @@ class MetabrowseServer(
332340
Some(textDocument)
333341
} catch {
334342
case NonFatal(e) =>
335-
logger.error(s"compile error: $filename", e)
343+
logger.error(s"compile error: $subPath", e)
336344
None
337345
}
338346
} yield TextDocuments(List(doc.withText(text)))

0 commit comments

Comments
 (0)