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 '%' */