@@ -368,10 +368,11 @@ private static void TryKillUvForPath(string serverSrcPath)
368368 if ( string . IsNullOrEmpty ( serverSrcPath ) ) return ;
369369 if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ) return ;
370370
371+ string safePath = EscapeForPgrep ( serverSrcPath ) ;
371372 var psi = new System . Diagnostics . ProcessStartInfo
372373 {
373374 FileName = "/usr/bin/pgrep" ,
374- Arguments = $ "-f \" uv .*--directory { serverSrcPath } \" ",
375+ Arguments = $ "-f \" uv .*--directory { safePath } \" ",
375376 UseShellExecute = false ,
376377 RedirectStandardOutput = true ,
377378 RedirectStandardError = true ,
@@ -406,6 +407,26 @@ private static string ReadVersionFile(string path)
406407 catch { return null ; }
407408 }
408409
410+ // Escape regex metacharacters so the path is treated literally by pgrep -f
411+ private static string EscapeForPgrep ( string path )
412+ {
413+ if ( string . IsNullOrEmpty ( path ) ) return path ;
414+ // Escape backslash first, then regex metacharacters
415+ string s = path . Replace ( "\\ " , "\\ \\ " ) ;
416+ char [ ] meta = new [ ] { '.' , '+' , '*' , '?' , '^' , '$' , '(' , ')' , '[' , ']' , '{' , '}' , '|' } ;
417+ var sb = new StringBuilder ( s . Length * 2 ) ;
418+ foreach ( char c in s )
419+ {
420+ if ( Array . IndexOf ( meta , c ) >= 0 )
421+ {
422+ sb . Append ( '\\ ' ) ;
423+ }
424+ sb . Append ( c ) ;
425+ }
426+ // Also escape double quotes which we wrap the pattern with
427+ return sb . ToString ( ) . Replace ( "\" " , "\\ \" " ) ;
428+ }
429+
409430 private static int CompareSemverSafe ( string a , string b )
410431 {
411432 try
0 commit comments