Am Mon, Sep 07, 2026 at 05:36:17PM +0200 schrieb Martin Guy:
> On 9/7/26 4:55 PM, Andrew L. Moore wrote:
> > On 2026-09-06 12:42, Harry Graf wrote:
> > > If the flag is set filenames will be escaped.
> > 
> > Okay, but what about the quoting implementation? Is wrapping in single
> > quotes sufficient?

Single quote escpaping is simple and works.
In my sololution a ' gets a <<'\''>>
stop single quoting, escaped single quote with \, starting
again single quoting.

> 
> I recently faced shell quoting because funny filenames allowed command
> injection in commands passed to popen(). The Unix and Windows rules are
> different: out solutin for Unix was to singlewuote the whole things and
> map single quotes into '\''.

Yes it is vulneralbe.

> 
> On Windows it's hairier as you need to double quote the whole thing
> to protect spaces, then some hack I don't really understand to defeat
> filenames that end in backslashes:

I think windows is not relevant for us.

Here is the soloution with the switch --unsafe-names and
a better implementation:

--- main.c.bak  2026-09-07 18:29:32.319320480 +0200
+++ main.c      2026-09-07 18:29:54.599616898 +0200
@@ -53,7 +53,7 @@
 static bool extended_regexp_ = false;  /* use EREs */
 static bool quiet = false;             /* suppress diagnostics */
 static bool restricted_ = false;       /* run in restricted mode */
-static bool safe_names = true;         /* reject control chars in file names */
+bool safe_names = true;                /* reject control chars in file names */
 static bool scripted_ = false;         /* suppress byte counts and ! prompt */
 static bool strip_cr_ = false;         /* strip trailing CRs */
 static bool traditional_ = false;      /* be backwards compatible */


--- main_loop.c.bak     2026-09-08 08:58:38.725634605 +0200
+++ main_loop.c 2026-09-08 08:45:54.139616875 +0200
@@ -35,6 +35,7 @@
 static const char * const no_cur_fn   = "No current filename";
 static const char * const no_prev_com = "No previous command";
 static const char * def_filename = ""; /* default filename */
+static const char * esc_filename = "";  /* default escaped filename */
 static char errmsg[80] = "";           /* error message buffer */
 static const char * prompt_str = "*";  /* command prompt */
 static int first_addr = 0, second_addr = 0;
@@ -52,11 +53,33 @@
   {
   static char * buf = 0;               /* filename buffer */
   static int bufsz = 0;                        /* filename buffer size */
-  const int len = strlen( s );
+  static char * esc = 0;         /* escaped filename buffer */
+  static int escsz = 0;          /* escaped size */
+  int i;
+  char *p;
+  int len = strlen( s );
 
   if( !resize_buffer( &buf, &bufsz, len + 1 ) ) return false;
   memcpy( buf, s, len + 1 );
   def_filename = buf;
+
+  if( !resize_buffer( &esc, &escsz, 4 * len + 3 ) ) return false;
+  p = esc;
+  *p++ = '\'';
+  for( i = 0; i < len; i++ ) {
+    if( buf[i] == '\'' ) {
+      *p++ = '\'';
+      *p++ = '\\';
+      *p++ = '\'';
+      *p++ = '\'';
+    } else {
+      *p++ = buf[i];
+    }
+  }
+  *p++ = '\'';
+  *p = '\0';
+  esc_filename = esc;
+
   read_only = false;
   return true;
   }
@@ -142,10 +165,14 @@
     {
     if( **ibufpp == '%' )      /* replace '%' with the default filename */
       {
+      extern bool safe_names;
+      const char *filename;
+
       if( !def_filename[0] ) { set_error_msg( no_cur_fn ); return 0; }
-      len = strlen( def_filename );
+      filename = safe_names? def_filename : esc_filename;
+      len = strlen( filename );
       if( !resize_buffer( &buf, &bufsz, i + len ) ) return 0;
-      memcpy( buf + i, def_filename, len );
+      memcpy( buf + i, filename, len );
       i += len; ++*ibufpp; replacement = true;
       }
     else               /* copy char or escape sequence unescaping any '%' */

Reply via email to