Skip to content

Broken Model loading if jar path contain url encoded characters #2576

@msosnicki

Description

@msosnicki

Hi,

I'm facing following issue when trying to load smithy model.
I have some local files that were downloaded from my internal, authenticated repository. The files therefore contain something like user%40my.internal.repo in the path (where %40 is url encoded form of @).

When I try to load such model (using regular Model.assembler().addImport), I get:

 software.amazon.smithy.model.loader.ModelManifestException: Error parsing Smithy model manifest from jar:file:/home/user/.cache/coursier/v1/https/user%40my.internal.repo/maven/com/disneystreaming/alloy/alloy-core/0.3.14/alloy-core-0.3.14.jar!/META-INF/smithy/manifest

Below is the minimized example, and the proposed fix. The toString on both URLs is exactly the same, however what is attempted to get opened is different. This is some deep java internals, and I don't have time to dig more into it, but looks like the fix I'm proposing will handle Paths that are provided by users butter in some rare scenarios.

Reproduced using scala-cli

//> using scala "3.3.5"
//> using dep "software.amazon.smithy:smithy-model:1.56.0"
import java.net.URI
import scala.util.Try
import software.amazon.smithy.model.loader.ModelDiscovery


val locGood = "/home/ssn/Documents/alloy-core-0.3.14.jar"
val locBad = "/home/ssn/Documents/alloy%40core-0.3.14.jar"

def tryOpen(location: String) = Try {
    val url = ModelDiscovery.createSmithyJarManifestUrl(location)
    url.openConnection().getInputStream()  
}

def createSmithyJarManifestUrlFixed(fileOrUrl: String) = {
    val jarEntry = "/META-INF/smithy/manifest"
    val fileUri = new URI("file", null, fileOrUrl, null)
    val jarUri = new URI("jar:" + fileUri.toString + "!" + jarEntry)
    jarUri.toURL
}


def tryOpenFixed(location: String) = Try {
    val url = createSmithyJarManifestUrlFixed(location)
    url.openConnection().getInputStream()
}


println("BROKEN")
List(locGood, locBad).foreach{ l =>
    println(s"Opening $l")
    println(tryOpen(l))
}

println("FIXED")
List(locGood, locBad).foreach{ l =>
    println(s"Opening $l")
    println(tryOpenFixed(l))
}

The above prints:

BROKEN
Opening /home/ssn/Documents/alloy-core-0.3.14.jar
Success(sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@246ae04d)
Opening /home/ssn/Documents/alloy%40core-0.3.14.jar
Failure(java.nio.file.NoSuchFileException: /home/ssn/Documents/[email protected])
FIXED
Opening /home/ssn/Documents/alloy-core-0.3.14.jar
Success(sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@4157f54e)
Opening /home/ssn/Documents/alloy%40core-0.3.14.jar
Success(sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@1936f0f5)

You can grab the same file I used for testing from

 curl -L -o alloy-core-0.3.14.jar \
    https://repo1.maven.org/maven2/com/disneystreaming/alloy/alloy-core/0.3.14/alloy-core-0.3.14.jar

I can prepare the PR for fix, and think about dropping in some test for it, but I would like to ask if there are any gotchas I should be aware or if the proposed fix looks good to you.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions