[X2Go-Commits] [x2goserver] 26/30: x2goserver/lib/x2goupdateoptionsstring: handle options in a more robust way.

git-admin at x2go.org git-admin at x2go.org
Thu Dec 13 11:22:51 CET 2018


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch master
in repository x2goserver.

commit 1759ca1e39f2c2a91abc9d37d5a40cef1bf902d2
Author: Mihai Moldovan <ionic at ionic.de>
Date:   Thu Dec 13 08:52:15 2018 +0100

    x2goserver/lib/x2goupdateoptionsstring: handle options in a more robust way.
    
    First, we scan for unknown options and error out. If we find a
    separating "--" pseudo-option, we keep that in mind and will not process
    further options next time. Do this for every run of the transformation
    loop.
---
 debian/changelog                       |   5 +
 x2goserver/lib/x2goupdateoptionsstring | 164 ++++++++++++++++++++++++++++++---
 2 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 8ee6e8d..24a3137 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -63,6 +63,11 @@ x2goserver (4.1.0.4-0x2go1) UNRELEASED; urgency=medium
       strings by replacing the switch statement with if statements.
       "Fallthrough" doesn't mean the same thing as in C, apparently. Buyer
       beware.
+    - x2goserver/lib/x2goupdateoptionsstring: handle options in a more robust
+      way. First, we scan for unknown options and error out. If we find a
+      separating "--" pseudo-option, we keep that in mind and will not process
+      further options next time. Do this for every run of the transformation
+      loop.
   * debian/control:
     + Build-depend upon lsb-release for distro version detection.
   * debian/x2goserver.manpages:
diff --git a/x2goserver/lib/x2goupdateoptionsstring b/x2goserver/lib/x2goupdateoptionsstring
index 1521d3e..6330d39 100755
--- a/x2goserver/lib/x2goupdateoptionsstring
+++ b/x2goserver/lib/x2goupdateoptionsstring
@@ -668,11 +668,107 @@ sub interpret_transform {
   return $ret;
 }
 
+# Helper function handling unknown options or ignoring the well-known
+# separator. It scans for options until hitting the first non-option entry.
+#
+# Takes an array reference with unparsed options and a boolean value denoting
+# whether the separating "--" pseudo-option should be skipped or not as its
+# parameters.
+#
+# Returns an array reference containing a boolean value denoting whether a
+# separating "--" pseudo-option has been found *and* skipping it was requested,
+# and the sanitized version of the original array reference.
+#
+# On error, returns undef.
+sub sanitize_program_options {
+  my $ret = undef;
+  my $error_detected = 0;
+  my $found_separator = 0;
+
+  my $args = shift;
+  my $skip_separator = shift;
+
+  if ((!(defined ($args))) || ('ARRAY' ne ref ($args))) {
+    print {*STDERR} "Invalid argument array reference passed to program sanitization helper, erroring out.\n";
+    $error_detected = 1;
+  }
+
+  if (!($error_detected)) {
+    if (!(defined ($skip_separator))) {
+      print {*STDERR} "No skip-separator parameter passed to program sanitization helper, erroring out.\n";
+      $error_detected = 1;
+    }
+  }
+
+  if (!($error_detected)) {
+    $args = dclone ($args);
+
+    my $opt = 1;
+    for (my $cur_arg = shift (@{$args}); ((defined ($cur_arg)) && ($opt)); $cur_arg = shift (@{$args})) {
+      if (q{-} eq substr ($cur_arg, 0, 1)) {
+        # Looks like an option so far. Let's continue scanning.
+
+        if (1 == length ($cur_arg)) {
+          # But isn't a real option. Add back to argument list and stop
+          # processing.
+          unshift (@{$args}, $cur_arg);
+          last;
+        }
+        elsif ((2 == length ($cur_arg)) && (q{-} eq substr ($cur_arg, 1, 1))) {
+          if ($skip_separator) {
+            # Found separating "--" pseudo-option, but skipping requested. Only
+            # set the boolean value for our return value.
+            $found_separator = 1;
+          }
+          else {
+            # Not skipping separating "--" pseudo-option - i.e., we'll treat this
+            # as a non-option.
+            unshift (@{$args}, $cur_arg);
+            last;
+          }
+        }
+        else {
+          # Otherwise this is an actual option.
+          # We either want to error out, if no previous separating "--"
+          # pseudo-option was found, or ignore it.
+          # The weird 0 + (...) construct here is forcing an arithmetic
+          # context. Otherwise, the interpreter might use a string context,
+          # in which the value "0" is dualvar'd to both an arithmetic 0 and
+          # an empty string.
+          my $separator_found = (0 + ((!($skip_separator)) | ($found_separator)));
+          if ($separator_found) {
+            # Put back into array. We'll handle this as not-an-option.
+            unshift (@{$args}, $cur_arg);
+            last;
+          }
+          else {
+            print {*STDERR} "Unknown option encountered: " . $cur_arg ."; erroring out.\n";
+            $error_detected = 1;
+            last;
+          }
+        }
+      }
+      else {
+        # Definitely not an option, add back to array.
+        unshift (@{$args}, $cur_arg);
+        last;
+      }
+    }
+  }
+
+  if (!($error_detected)) {
+    $ret = [ $found_separator, $args ];
+  }
+
+  return $ret;
+}
+
 # Main function, no code outside of it shall be executed.
 #
 # Expects @ARGV to be passed in.
 sub Main {
   my $error_detected = 0;
+  my $found_separator = 0;
 
   Getopt::Long::Configure ('gnu_getopt', 'no_auto_abbrev', 'pass_through');
 
@@ -689,13 +785,28 @@ sub Main {
     pod2usage (-verbose => 2, -exitval => 3);
   }
 
-  my $options = shift;
+  my $sanitized_options = sanitize_program_options (\@_, (!($found_separator)));
 
-  if (!(defined ($options))) {
-    print {*STDERR} "No options string given, aborting.\n";
+  if (!(defined ($sanitized_options))) {
+    pod2usage (-exitval => 'NOEXIT');
     $error_detected = 4;
   }
 
+  my $options = undef;
+
+  if (!($error_detected)) {
+    $found_separator |= (0 + shift (@{$sanitized_options}));
+    $sanitized_options = shift (@{$sanitized_options});
+    @_ = @{$sanitized_options};
+
+    $options = shift;
+
+    if (!(defined ($options))) {
+      print {*STDERR} "No options string given, aborting.\n";
+      $error_detected = 5;
+    }
+  }
+
   my $intermediate = undef;
 
   if (!($error_detected)) {
@@ -707,11 +818,24 @@ sub Main {
 
     if (!(defined ($intermediate))) {
       print {*STDERR} "Unable to parse option string, aborting.\n";
-      $error_detected = 5;
+      $error_detected = 6;
     }
   }
 
   if (!($error_detected)) {
+    $sanitized_options = sanitize_program_options (\@_, (!($found_separator)));
+
+    if (!(defined ($sanitized_options))) {
+      pod2usage (-exitval => 'NOEXIT');
+      $error_detected = 7;
+    }
+  }
+
+  if (!($error_detected)) {
+    $found_separator |= (0 + shift (@{$sanitized_options}));
+    $sanitized_options = shift (@{$sanitized_options});
+    @_ = @{$sanitized_options};
+
     my $cur_transform = shift;
 
     if ($debug) {
@@ -719,13 +843,16 @@ sub Main {
     }
 
     # Nasty trick (to some degree): "do"-blocks are not recognized as loops by
-    # Perl, but we can wrap the body in another block, which WILL BE recognized
-    # as a loop (one, that only executes once), oddly enough.
-    do {{
+    # Perl, but we could wrap the body in another block, which WILL BE recognized
+    # as a loop (one, that only executes once), oddly enough. However, using
+    # "last" won't work in such a situation, but rather behave like "next".
+    # Worse, the condition will also not be checked in such a case.
+    # Thus, we'd better use a real loop.
+    while (1) {
       # Shall only be relevant for the first run of the loop.
       if (!(defined ($cur_transform))) {
         print {*STDERR} "No transformation passed, aborting.\n";
-        $error_detected = 6;
+        $error_detected = 8;
         last;
       }
 
@@ -737,7 +864,7 @@ sub Main {
 
       if (!(defined ($interpreted_transform_ref))) {
         print {*STDERR} "Invalid transformation passed, aborting.\n";
-        $error_detected = 7;
+        $error_detected = 9;
         last;
       }
 
@@ -751,14 +878,27 @@ sub Main {
 
       if (!(defined ($intermediate))) {
         print {*STDERR} "Error while transforming intermediate representation, aborting.\n";
-        $error_detected = 7;
+        $error_detected = 10;
         last;
       }
 
       if ($debug) {
         print {*STDERR} 'Dumping transformed intermediate array: ' . Dumper ($intermediate);
       }
-    }} while (defined ($cur_transform = shift));
+
+      # Skip pseudo-option, if necessary.
+      $sanitized_options = sanitize_program_options (\@_, (!($found_separator)));
+
+      if (!(defined ($sanitized_options))) {
+        pod2usage (-exitval => 'NOEXIT');
+        $error_detected = 11;
+        last;
+      }
+
+      $found_separator |= (0 + shift (@{$sanitized_options}));
+      $sanitized_options = shift (@{$sanitized_options});
+      @_ = @{$sanitized_options};
+    } continue { last unless (defined ($cur_transform = shift)) };
   }
 
   my $out = undef;
@@ -768,7 +908,7 @@ sub Main {
 
     if (!(defined ($out))) {
       print {*STDERR} "Unable to transform intermediate back into string, aborting.\n";
-      $error_detected = 8;
+      $error_detected = 12;
     }
   }
 

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/x2goserver.git


More information about the x2go-commits mailing list