Configure: avoid perl regexp bugs
authorRichard Levitte <levitte@openssl.org>
Tue, 5 May 2020 14:53:43 +0000 (16:53 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 6 May 2020 18:16:25 +0000 (20:16 +0200)
It seems that in older perl versions '(?P' doesn't interact very well
with '(?|' or '(?:'.

Since we make extensive use of '(?P' in build.info parsing, we avoid
combining that with '(?|' and '(?:' when parsing build.info variables,
and end up parsing variable modifier twice (first generally, and then
parse that result into the modifier components).

Fixes #11694

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11737)

Configure

index 4a23d26..7738073 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -1831,23 +1831,13 @@ if ($builder eq "unified") {
         my $variable_name_re = qr/(?P<VARIABLE>[[:alpha:]][[:alnum:]_]*)/;
         # Value modifier syntaxes
         my $variable_subst_re = qr/\/(?P<RE>(?:\\\/|.)*?)\/(?P<SUBST>.*?)/;
-        # Put it all together
-        my $variable_re = qr/\$
-                             (?|
-                                 # Simple case, just the name
-                                 ${variable_name_re}
-                             |
-                                 # Expressive case, with braces and possible
-                                 # modifier expressions
-                                 \{
-                                 ${variable_name_re}
-                                 (?:
-                                     # Pile on modifier expressions,
-                                     # separated by |
-                                     ${variable_subst_re}
-                                 )
-                                 \}
-                             )/x;
+        # Variable reference
+        my $variable_simple_re = qr/(?<!\\)\$${variable_name_re}/;
+        my $variable_w_mod_re =
+            qr/(?<!\\)\$\{${variable_name_re}(?P<MOD>(?:\\\/|.)*?)\}/;
+        # Tie it all together
+        my $variable_re = qr/${variable_simple_re}|${variable_w_mod_re}/;
+
         my $expand_variables = sub {
             my $value = '';
             my $value_rest = shift;
@@ -1856,25 +1846,29 @@ if ($builder eq "unified") {
                 print STDERR
                     "DEBUG[\$expand_variables] Parsed '$value_rest' ...\n"
             }
-            while ($value_rest =~ /(?<!\\)${variable_re}/) {
-                $value_rest = $';
-                $value .= $`;
 
+            while ($value_rest =~ /${variable_re}/) {
+                # We must save important regexp values, because the next
+                # regexp clears them
+                my $mod = $+{MOD};
                 my $variable_value = $variables{$+{VARIABLE}};
 
+                $value_rest = $';
+                $value .= $`;
+
                 # Process modifier expressions, if present
-                if (defined $+{RE}) {
-                    # We must save important %+ values, because the s///
-                    # below clears them
-                    my $re = $+{RE};
-                    my $subst = $+{SUBST};
-
-                    $variable_value =~ s/\Q$re\E/$subst/g;
-
-                    if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
-                        print STDERR
-                            "DEBUG[\$expand_variables] ... and substituted ",
-                            "'$re' with '$subst'\n";
+                if (defined $mod) {
+                    if ($mod =~ /^${variable_subst_re}$/) {
+                        my $re = $+{RE};
+                        my $subst = $+{SUBST};
+
+                        $variable_value =~ s/\Q$re\E/$subst/g;
+
+                        if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
+                            print STDERR
+                                "DEBUG[\$expand_variables] ... and substituted ",
+                                "'$re' with '$subst'\n";
+                        }
                     }
                 }