gleam-lang / gleam

⭐️ A friendly language for building type-safe, scalable systems!
https://gleam.run
Apache License 2.0
16.7k stars 698 forks source link

Disallow creating new projects in non-utf8 paths #2888

Closed zahash closed 3 months ago

zahash commented 3 months ago

gleam won't let me create a project with non utf8 name but i can create a project in a directory where one of the path segments is non-utf8.

eg:

mkdir $'\xC0\xC0'
cd $'\xC0\xC0'

gleam new samplegleam
cd simplegleam

however this is NOT the intended behavior beause when i run any command, like gleam build or gleam run etc... they all fail.

error: Fatal compiler bug!

This is a bug in the Gleam compiler, sorry!

Please report this crash to https://github.com/gleam-lang/gleam/issues/new
and include this error message with your report.

Panic: compiler-cli/src/main.rs:558
    Failed to get current directory: NonUtf8Path { path: "/home/zahash/source/\xC0\xC0/samplegleam" }
Gleam version: 1.0.0
Operating system: linux

If you can also share your code and say what file you were editing or any
steps to reproduce the crash that would be a great help.

You may also want to try again with the `GLEAM_LOG=trace` environment
variable set.

the problem is because when i do gleam new samplegleam, the NewOptions.project_root: String is set to "simplegleam". and the Creator::new function makes a Utf8PathBuf with just the "simplegleam" string and doesn't check its full path /home/zahash/source/��/samplegleam

the root cause of this is the improper path checking when a new instance of Utf8PathBuf is created from a String. it assumes that since the Utf8PathBuf is created from a String it must be valid utf8. But it fails to consider that the String might be just a relative path. The absolute path might contain non-utf8 segments.

impl Creator {
    fn new(options: NewOptions, gleam_version: &'static str) -> Result<Self, Error> {
        // ...
        let root = Utf8PathBuf::from(&options.project_root);
        // ...
    }
}

the reason why gleam run and gleam clean catch this error is because they use find_project_paths function which uses get_current_directory which uses std::env::current_dir() which gives the absolute path of the current directory. So, when it is converted to Utf8PathBuf, it fails.

// compiler-cli/src/run.rs
pub fn command(
    arguments: Vec<String>,
    target: Option<Target>,
    runtime: Option<Runtime>,
    module: Option<String>,
    which: Which,
) -> Result<(), Error> {
    let paths = crate::find_project_paths()?;
    // ...
}

// compiler-cli/src/main.rs
fn find_project_paths() -> Result<ProjectPaths> {
    let current_dir = get_current_directory()?;
    get_project_root(current_dir).map(ProjectPaths::new)
}

but the gleam new command uses a different function as mentioned above

// compiler-cli/src/new.rs
pub fn create(options: NewOptions, version: &'static str) -> Result<()> {
    let creator = Creator::new(options.clone(), version)?;
    // ...
}

impl Creator {
    fn new(options: NewOptions, gleam_version: &'static str) -> Result<Self, Error> {
        // ...
        let root = Utf8PathBuf::from(&options.project_root); // THE BUG IS HERE!!
        // ...
    }
}
zahash commented 3 months ago

@lpil

here is the PR that fixes this https://github.com/gleam-lang/gleam/pull/2889