On Tue, Mar 14, 2023 at 08:43:52AM +0100, Peter Bex wrote:
> On Tue, Mar 14, 2023 at 08:40:18AM +0100, felix.winkelm...@bevuta.com wrote:
> > Backwards compatibility is from now on fucked anyway, so let's
> > try to find somethin simple and sensible.
> 
> Then we should do both.  I.e., have -: to explicitly tell it to stop
> parsing (and have that dropped from the command-line-options) and
> stop at the first argument.  The -: would be in situations where
> a script just passes on all its arguments, like
> 
> ./my-program -: "$@"

Here's a patch that implements this proposal.

Cheers,
Peter

From dce61eb2d7caf7f570701161ee1cada07a862835 Mon Sep 17 00:00:00 2001
From: Peter Bex <pe...@more-magic.net>
Date: Fri, 24 Mar 2023 10:42:49 +0100
Subject: [PATCH] Stop run-time option processing after "-:" or the first
 non-runtime option

This means that runtime options after non-runtime options will no
longer be processed.  Programs using command-line-arguments will
see all options starting at the first non-runtime option, even if
later options start with "-:".

Processing can also be stopped explicitly with a single "-:" option,
which will not be seen by programs using command-line-arguments.
Every argument following this "-:" will be seen, even if they start
with "-:".
---
 NEWS                                    |   4 +
 library.scm                             |  22 +-
 manual/Module (chicken process-context) |  22 +-
 manual/Using the compiler               |  15 +-
 runtime.c                               | 258 ++++++++++++------------
 5 files changed, 179 insertions(+), 142 deletions(-)

diff --git a/NEWS b/NEWS
index 23661fc2..6ecbbad2 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@
     to avoid arbitrary OS command injection during egg installation,
     reported by Vasilij Schneidermann who also provided the necessary
     patches to mitigate this problem.
+  - The runtime option "-:b" has been removed, as it was deemed too
+    insecure to be able to drop to a REPL from the CLI of any program.
+  - Runtime option processing has been hardened: processing now stops on
+    the first non-runtime option or after "-:", whichever comes first.
 
 - Core libraries
   - Added "locative-index", kindly contributed by John Croisant.
diff --git a/library.scm b/library.scm
index 827666d5..819dacfe 100644
--- a/library.scm
+++ b/library.scm
@@ -6024,17 +6024,23 @@ static C_word C_fcall C_setenv(C_word x, C_word y) {
 
 (define command-line-arguments
   (make-parameter
-   (let ([args (argv)])
+   (let ((args (argv)))
      (if (pair? args)
-        (let loop ([args (##sys#slot args 1)])
+        (let loop ((args (##sys#slot args 1))) ; Skip over program name 
(argv[0])
           (if (null? args)
               '()
-              (let ([arg (##sys#slot args 0)]
-                    [r (##sys#slot args 1)] )
-                (if (and (fx>= (##sys#size arg) 3)
-                         (string=? "-:" (##sys#substring arg 0 2)))
-                    (loop r)
-                    (cons arg (loop r)) ) ) ) )
+              (let ((arg (##sys#slot args 0))
+                    (rest (##sys#slot args 1)) )
+                (cond
+                 ((string=? "-:" arg)  ; Consume first "empty" runtime options 
list, return rest
+                  rest)
+
+                 ((and (fx>= (##sys#size arg) 3)
+                       (string=? "-:" (##sys#substring arg 0 2)))
+                  (loop rest))
+
+                 ;; First non-runtime option and everything following it is 
returned as-is
+                 (else args) ) ) ) )
         args) )
    (lambda (x)
      (##sys#check-list x 'command-line-arguments)
diff --git a/manual/Module (chicken process-context) b/manual/Module (chicken 
process-context)
index 5299905e..87165187 100644
--- a/manual/Module (chicken process-context)   
+++ b/manual/Module (chicken process-context)   
@@ -13,7 +13,7 @@ This module provides access to the current process context.
 
 Returns two values: an integer and a foreign-pointer object
 representing the {{argc}} and {{argv}} arguments passed to the current
-process.
+process.  See also {{argv}} below.
 
 ==== argv
 
@@ -24,13 +24,27 @@ the list is a string containing the name of the executing 
program. The
 other items are the arguments passed to the application. It depends on
 the host-shell whether arguments are expanded ('globbed') or not.
 
+NOTE: This is the "raw" unprocessed argument list, including runtime
+options (starting with {{-:}}) which are consumed by the runtime
+library.
+
 ==== command-line-arguments
 
 <parameter>(command-line-arguments)</parameter>
 
-Contains the list of arguments passed to this program, with the name of
-the program and any runtime options (all options starting with {{-:}})
-removed.
+Contains the list of arguments passed to this program.
+
+This ''excludes'' the name of the program, as well as any runtime
+options (options starting with {{-:}}) up until the first empty
+runtime option (just {{"-:"}}) or non-runtime option, whichever
+comes first.
+
+In other words, this method returns every option ''after'' the first
+list of unbroken runtime options, which are all skipped.  If an empty
+runtime option is present, that is the last of this list of unbroken
+runtime options and everything after it is returned by this method.
+If a non-runtime option is present, that also breaks up the runtime
+options and this method returns that and every following option.
 
 ==== executable-pathname
 
diff --git a/manual/Using the compiler b/manual/Using the compiler
index 30e5ed2a..e9eb3672 100644
--- a/manual/Using the compiler 
+++ b/manual/Using the compiler 
@@ -220,10 +220,17 @@ to see a list of all supported options and short aliases 
to basic options.
 === Runtime options
 
 After successful compilation a C source file is generated and can be
-compiled with a C compiler. Executables generated with CHICKEN (and the
-compiler itself) accept a small set of runtime options. These are filtered out
-by the startup code and will not be contained in the result of 
-{{(command-line-arguments)}}.
+compiled with a C compiler. Executables generated with CHICKEN (and
+the compiler itself) accept a small set of runtime options.
+Processing of these options stops at the first non-runtime option, or
+''after'' the empty runtime option (just "{{-:}}"), whichever comes
+first.
+
+In other words, the program sees every option after the first list of
+unbroken runtime options, which are all consumed.  If an empty runtime
+option is present, that is the last of this list of unbroken runtime
+options.  If a non-runtime option is present, that also breaks up the
+runtime options.
 
 ; {{-:?}} : Shows a list of the available runtime options and exits the 
program.
 
diff --git a/runtime.c b/runtime.c
index aa64092b..ac7f2392 100644
--- a/runtime.c
+++ b/runtime.c
@@ -1348,153 +1348,159 @@ void CHICKEN_parse_command_line(int argc, char 
*argv[], C_word *heap, C_word *st
   *stack = DEFAULT_STACK_SIZE;
   *symbols = DEFAULT_SYMBOL_TABLE_SIZE;
 
-  for(i = 1; i < C_main_argc; ++i)
-    if(!strncmp(C_main_argv[ i ], C_text("-:"), 2)) {
-      for(ptr = &C_main_argv[ i ][ 2 ]; *ptr != '\0';) {
-       switch(*(ptr++)) {
-       case '?':
-         C_dbg("Runtime options", "\n\n"
-                " -:?              display this text\n"
-                " -:c              always treat stdin as console\n"
-                " -:d              enable debug output\n"
-                " -:D              enable more debug output\n"
-                " -:g              show GC information\n"
-                " -:o              disable stack overflow checks\n"
-                " -:hiSIZE         set initial heap size\n"
-                " -:hmSIZE         set maximal heap size\n"
-                 " -:hfSIZE         set minimum unused heap size\n"
-                " -:hgPERCENTAGE   set heap growth percentage\n"
-                " -:hsPERCENTAGE   set heap shrink percentage\n"
-                " -:huPERCENTAGE   set percentage of memory used at which heap 
will be shrunk\n"
-                " -:hSIZE          set fixed heap size\n"
-                " -:r              write trace output to stderr\n"
-                " -:RSEED          initialize rand() seed with SEED (helpful 
for benchmark stability)\n"
-                " -:p              collect statistical profile and write to 
file at exit\n"
-                " -:PFREQUENCY     like -:p, specifying sampling frequency in 
us (default: 10000)\n"
-                " -:sSIZE          set nursery (stack) size\n"
-                " -:tSIZE          set symbol-table size\n"
-                 " -:fSIZE          set maximal number of pending finalizers\n"
-                " -:x              deliver uncaught exceptions of other 
threads to primordial one\n"
-                " -:B              sound bell on major GC\n"
-                " -:G              force GUI mode\n"
-                " -:aSIZE          set trace-buffer/call-chain size\n"
-                " -:ASIZE          set fixed temporary stack size\n"
-                " -:H              dump heap state on exit\n"
-                " -:S              do not handle segfaults or other serious 
conditions\n"
-                "\n  SIZE may have a `k' (`K'), `m' (`M') or `g' (`G') suffix, 
meaning size\n"
-                "  times 1024, 1048576, and 1073741824, respectively.\n\n");
-         C_exit_runtime(C_fix(0));
-
-       case 'h':
-         switch(*ptr) {
-         case 'i':
-           *heap = arg_val(ptr + 1); 
-           heap_size_changed = 1;
-           goto next;
-          case 'f':
-           C_heap_half_min_free = arg_val(ptr + 1);
-           goto next;
-         case 'g':
-           C_heap_growth = arg_val(ptr + 1);
-           goto next;
-         case 'm':
-           C_maximal_heap_size = arg_val(ptr + 1);
-           goto next;
-         case 's':
-           C_heap_shrinkage = arg_val(ptr + 1);
-           goto next;
-         case 'u':
-           C_heap_shrinkage_used = arg_val(ptr + 1);
-           goto next;
-         default:
-           *heap = arg_val(ptr); 
-           heap_size_changed = 1;
-           C_heap_size_is_fixed = 1;
-           goto next;
-         }
+  for(i = 1; i < C_main_argc; ++i) {
+    if (strncmp(C_main_argv[ i ], C_text("-:"), 2))
+      break; /* Stop parsing on first non-runtime option */
 
-       case 'o':
-         C_disable_overflow_check = 1;
-         break;
+    ptr = &C_main_argv[ i ][ 2 ];
+    if (*ptr == '\0')
+      break; /* Also stop parsing on first "empty" option (i.e. "-:") */
 
-       case 'B':
-         gc_bell = 1;
-         break;
+    do {
+      switch(*(ptr++)) {
+      case '?':
+        C_dbg("Runtime options", "\n\n"
+              " -:?              display this text\n"
+              " -:c              always treat stdin as console\n"
+              " -:d              enable debug output\n"
+              " -:D              enable more debug output\n"
+              " -:g              show GC information\n"
+              " -:o              disable stack overflow checks\n"
+              " -:hiSIZE         set initial heap size\n"
+              " -:hmSIZE         set maximal heap size\n"
+              " -:hfSIZE         set minimum unused heap size\n"
+              " -:hgPERCENTAGE   set heap growth percentage\n"
+              " -:hsPERCENTAGE   set heap shrink percentage\n"
+              " -:huPERCENTAGE   set percentage of memory used at which heap 
will be shrunk\n"
+              " -:hSIZE          set fixed heap size\n"
+              " -:r              write trace output to stderr\n"
+              " -:RSEED          initialize rand() seed with SEED (helpful for 
benchmark stability)\n"
+              " -:p              collect statistical profile and write to file 
at exit\n"
+              " -:PFREQUENCY     like -:p, specifying sampling frequency in us 
(default: 10000)\n"
+              " -:sSIZE          set nursery (stack) size\n"
+              " -:tSIZE          set symbol-table size\n"
+              " -:fSIZE          set maximal number of pending finalizers\n"
+              " -:x              deliver uncaught exceptions of other threads 
to primordial one\n"
+              " -:B              sound bell on major GC\n"
+              " -:G              force GUI mode\n"
+              " -:aSIZE          set trace-buffer/call-chain size\n"
+              " -:ASIZE          set fixed temporary stack size\n"
+              " -:H              dump heap state on exit\n"
+              " -:S              do not handle segfaults or other serious 
conditions\n"
+              "\n  SIZE may have a `k' (`K'), `m' (`M') or `g' (`G') suffix, 
meaning size\n"
+              "  times 1024, 1048576, and 1073741824, respectively.\n\n");
+        C_exit_runtime(C_fix(0));
+
+      case 'h':
+        switch(*ptr) {
+        case 'i':
+          *heap = arg_val(ptr + 1); 
+          heap_size_changed = 1;
+          goto next;
+        case 'f':
+          C_heap_half_min_free = arg_val(ptr + 1);
+          goto next;
+        case 'g':
+          C_heap_growth = arg_val(ptr + 1);
+          goto next;
+        case 'm':
+          C_maximal_heap_size = arg_val(ptr + 1);
+          goto next;
+        case 's':
+          C_heap_shrinkage = arg_val(ptr + 1);
+          goto next;
+        case 'u':
+          C_heap_shrinkage_used = arg_val(ptr + 1);
+          goto next;
+        default:
+          *heap = arg_val(ptr); 
+          heap_size_changed = 1;
+          C_heap_size_is_fixed = 1;
+          goto next;
+        }
 
-       case 'G':
-         C_gui_mode = 1;
-         break;
+      case 'o':
+        C_disable_overflow_check = 1;
+        break;
 
-       case 'H':
-         dump_heap_on_exit = 1;
-         break;
+      case 'B':
+        gc_bell = 1;
+        break;
 
-       case 'S':
-         pass_serious_signals = 1;
-         break;
+      case 'G':
+        C_gui_mode = 1;
+        break;
 
-       case 's':
-         *stack = arg_val(ptr);
-         stack_size_changed = 1;
-         goto next;
+      case 'H':
+        dump_heap_on_exit = 1;
+        break;
 
-       case 'f':
-         C_max_pending_finalizers = arg_val(ptr);
-         goto next;
+      case 'S':
+        pass_serious_signals = 1;
+        break;
 
-       case 'a':
-         C_trace_buffer_size = arg_val(ptr);
-         goto next;
+      case 's':
+        *stack = arg_val(ptr);
+        stack_size_changed = 1;
+        goto next;
 
-       case 'A':
-         fixed_temporary_stack_size = arg_val(ptr);
-         goto next;
+      case 'f':
+        C_max_pending_finalizers = arg_val(ptr);
+        goto next;
 
-       case 't':
-         *symbols = arg_val(ptr);
-         goto next;
+      case 'a':
+        C_trace_buffer_size = arg_val(ptr);
+        goto next;
 
-       case 'c':
-         fake_tty_flag = 1;
-         break;
+      case 'A':
+        fixed_temporary_stack_size = arg_val(ptr);
+        goto next;
 
-       case 'd':
-         debug_mode = 1;
-         break;
+      case 't':
+        *symbols = arg_val(ptr);
+        goto next;
 
-       case 'D':
-         debug_mode = 2;
-         break;
+      case 'c':
+        fake_tty_flag = 1;
+        break;
 
-       case 'g':
-         gc_report_flag = 2;
-         break;
+      case 'd':
+        debug_mode = 1;
+        break;
 
-       case 'P':
-         profiling = 1;
-         profile_frequency = arg_val(ptr);
-          goto next;
+      case 'D':
+        debug_mode = 2;
+        break;
 
-       case 'p':
-         profiling = 1;
-          break;
+      case 'g':
+        gc_report_flag = 2;
+        break;
 
-       case 'r':
-         show_trace = 1;
-         break;
+      case 'P':
+        profiling = 1;
+        profile_frequency = arg_val(ptr);
+        goto next;
 
-       case 'R':
-         srand((unsigned int)arg_val(ptr));
-         random_state_initialized = 1;
-         goto next;
+      case 'p':
+        profiling = 1;
+        break;
 
-       case 'x':
-         C_abort_on_thread_exceptions = 1;
-         break;
+      case 'r':
+        show_trace = 1;
+        break;
 
-       default: panic(C_text("illegal runtime option"));
-       }
+      case 'R':
+        srand((unsigned int)arg_val(ptr));
+        random_state_initialized = 1;
+        goto next;
+
+      case 'x':
+        C_abort_on_thread_exceptions = 1;
+        break;
+
+      default: panic(C_text("illegal runtime option"));
       }
+    } while(*ptr != '\0');
 
     next:;
     }
-- 
2.38.4

Attachment: signature.asc
Description: PGP signature

Reply via email to