Skip to content

[BUG] SQL LIKE wildcard characters in path prefix cause incorrect search results #175

@calm329

Description

@calm329

Project

vgrep

Description

The search_similar() function in src/core/db.rs does not escape SQL LIKE wildcard characters (_ and %) in path prefixes. This causes searches to return files from unintended directories when the path contains underscores.

Error Message

Debug Logs

System Information

## Operating System
  ProductName:		macOS
  ProductVersion:		26.2
  BuildVersion:		25C56
  Arch: arm64

## Hardware
  CPU: Apple M4 Pro
  RAM: 24 GB

## Build Environment
  Rust: rustc 1.92.0 (ded5c06cf 2025-12-08)
  Target: aarch64

Screenshots

No response

Steps to Reproduce

  1. Create a project structure with similarly-named directories:

    /home/user/my_project/main.rs
    /home/user/my-project/main.rs
    /home/user/myXproject/main.rs
    
  2. Index all directories with vgrep

  3. Search with path prefix /home/user/my_project:

    db.search_similar(&embedding, Path::new("/home/user/my_project"), 10);
  4. Observe that files from my-project and myXproject are also returned

Minimal reproduction:

use rusqlite::{params, Connection};

fn main() {
    let conn = Connection::open_in_memory().unwrap();
    conn.execute_batch("CREATE TABLE files (path TEXT);").unwrap();

    conn.execute("INSERT INTO files VALUES (?)", params!["/home/user/my_project/main.rs"]).unwrap();
    conn.execute("INSERT INTO files VALUES (?)", params!["/home/user/my-project/main.rs"]).unwrap();
    conn.execute("INSERT INTO files VALUES (?)", params!["/home/user/myXproject/main.rs"]).unwrap();

    // This is what vgrep does at src/core/db.rs line 162
    let pattern = format!("{}%", "/home/user/my_project");

    let mut stmt = conn.prepare("SELECT path FROM files WHERE path LIKE ?").unwrap();
    let paths: Vec<String> = stmt.query_map([&pattern], |r| r.get(0)).unwrap().filter_map(Result::ok).collect();

    println!("Expected: 1 result, Got: {} results", paths.len());
    // Output: Expected: 1 result, Got: 3 results
}

Expected Behavior

Searching for path prefix /home/user/my_project should only return files under that exact directory:

  • /home/user/my_project/main.rs

Actual Behavior

Search returns files from unrelated directories because _ is a SQL LIKE wildcard matching any single character:

  • /home/user/my_project/main.rs ✓ (correct)
  • /home/user/my-project/main.rs ✗ (unintended)
  • /home/user/myXproject/main.rs ✗ (unintended)

Additional Context

Root cause: Line 162 constructs the LIKE pattern without escaping:

let like_pattern = format!("{}%", path_prefix_str);

Suggested fix:

fn escape_like_pattern(s: &str) -> String {
    s.replace('\\', "\\\\").replace('%', "\\%").replace('_', "\\_")
}

let like_pattern = format!("{}%", escape_like_pattern(&path_prefix_str));

And update the SQL query to include ESCAPE '\' clause.

Impact: Underscores are common in project names (node_modules, test_utils, my_app), making this bug likely to affect real users.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginvalidThis doesn't seem right

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions