8000 Unsoundness in run_ctags · Issue #101 · inherd/coco · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Unsoundness in run_ctags #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lwz23 opened this issue Mar 4, 2025 · 1 comment
Open

Unsoundness in run_ctags #101

lwz23 opened this issue Mar 4, 2025 · 1 comment

Comments

@lwz23
Copy link
lwz23 commented Mar 4, 2025

Hello, thank you for your contribution in this project, I an testing our static analysis tool in github's Rust project and I notice the following code:

fn run_ctags(opt: &Opt, files: &Vec<String>) -> Vec<ClassInfo> {
    let outputs = CmdCtags::call(&opt, &files).unwrap();
    let mut iters = Vec::new();
    for o in &outputs {
        let iter = if opt.validate_utf8 {
            str::from_utf8(&o.stdout).unwrap().lines()
        } else {
            unsafe { str::from_utf8_unchecked(&o.stdout).lines() }
        };
        iters.push(iter);
    }
    let parser = CtagsParser::parse_str(iters);
    let classes = parser.classes();
    classes
}

The issue is in the run_ctags function where it uses str::from_utf8_unchecked on external command output:

let iter = if opt.validate_utf8 {
    str::from_utf8(&o.stdout).unwrap().lines()
} else {
    unsafe { str::from_utf8_unchecked(&o.stdout).lines() }
};

Since o.stdout comes from an external program (ctags), there's no guarantee the data is valid UTF-8. If opt.validate_utf8 is false (which can be controlled through the configuration because I notice this is a pub field), the program will use str::from_utf8_unchecked on potentially invalid UTF-8 data, causing undefined behavior.
A valid path to call this fn: pub fn execute -> fn run_ctags

POC

fn main() {
    // Create a configuration with a repo that points to an existing directory
    let config = CocoConfig {
        repos: vec![RepoConfig {
            url: String::from("/tmp/test_repo"),  // Point to any directory
            languages: Some(vec![String::from("rust")]),
            // Other fields initialized as needed
        }],
        plugins: vec![PluginConfig {
            name: String::from("struct_analysis"),
            configs: vec![
                KeyValue {
                    key: String::from("ctags"),
                    value: String::from("/usr/bin/ctags"),  // Path to ctags binary
                }
            ]
        }]
    };
    
    // This will eventually call run_ctags, which uses str::from_utf8_unchecked
    // on the output of an external program (ctags) when validate_utf8 is false
    execute(config);
}
@phodal
Copy link
Member
phodal commented Mar 4, 2025

just give a PR?

Assignees
No one assigned
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0