texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

branch master updated: * tp/Texinfo/ParserNonXS.pm (%parser_state_initia


From: Patrice Dumas
Subject: branch master updated: * tp/Texinfo/ParserNonXS.pm (%parser_state_initialization, _next_text) (_process_remaining_on_line): add a value_stack to put expanded @value. Use a sourcemark structure put in source_info to mark the end of @value expansion. Also use such a structure for @macro, replacing 'end_macro'. Check number of values expansion number and error out if there is more than MAX_MACRO_CALL_NESTING. correct MAX_MACRO_CALL_NESTING name in warning message.
Date: Thu, 05 Jan 2023 16:55:25 -0500

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

pertusus pushed a commit to branch master
in repository texinfo.

The following commit(s) were added to refs/heads/master by this push:
     new e3d0afa566 * tp/Texinfo/ParserNonXS.pm (%parser_state_initialization, 
_next_text) (_process_remaining_on_line): add a value_stack to put expanded 
@value.  Use a sourcemark structure put in source_info to mark the end of 
@value expansion.  Also use such a structure for @macro, replacing 'end_macro'. 
Check number of values expansion number and error out if there is more than 
MAX_MACRO_CALL_NESTING. correct MAX_MACRO_CALL_NESTING name in warning message.
e3d0afa566 is described below

commit e3d0afa5660abe191f8d7b76ed27ba14c3583703
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Thu Jan 5 22:55:02 2023 +0100

    * tp/Texinfo/ParserNonXS.pm (%parser_state_initialization, _next_text)
    (_process_remaining_on_line): add a value_stack to put expanded
    @value.  Use a sourcemark structure put in source_info to mark
    the end of @value expansion.  Also use such a structure for
    @macro, replacing 'end_macro'.
    Check number of values expansion number and error out if
    there is more than MAX_MACRO_CALL_NESTING.
    correct MAX_MACRO_CALL_NESTING name in warning message.
    
    * tp/Texinfo/XS/parsetexi/Parsetexi.pm (parser),
    tp/Texinfo/XS/parsetexi/Parsetexi.xs
    (conf_set_MAX_MACRO_CALL_NESTING), tp/Texinfo/XS/parsetexi/conf.c
    (conf_set_MAX_MACRO_CALL_NESTING, reset_conf),
    tp/Texinfo/XS/parsetexi/macro.c (handle_macro): pass
    MAX_MACRO_CALL_NESTING to the XS parser.  Use that value for the
    number of macro call nesting allowed.
    correct MAX_MACRO_CALL_NESTING name in warning message.
    
    * tp/t/60macro.t: add recursive_call_in_rmacro to test for an infinite
    recursion.
---
 ChangeLog                                      |  23 +++++
 tp/TODO                                        |   5 +-
 tp/Texinfo/ParserNonXS.pm                      |  51 ++++++++--
 tp/Texinfo/XS/parsetexi/Parsetexi.pm           |   2 +
 tp/Texinfo/XS/parsetexi/Parsetexi.xs           |   3 +
 tp/Texinfo/XS/parsetexi/conf.c                 |   7 ++
 tp/Texinfo/XS/parsetexi/conf.h                 |   2 +
 tp/Texinfo/XS/parsetexi/macro.c                |   7 +-
 tp/t/60macro.t                                 |  11 +++
 tp/t/results/macro/recursive_call_in_rmacro.pl | 124 +++++++++++++++++++++++++
 10 files changed, 220 insertions(+), 15 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a871a5b752..d416b25a45 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2023-01-05  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/ParserNonXS.pm (%parser_state_initialization, _next_text)
+       (_process_remaining_on_line): add a value_stack to put expanded
+       @value.  Use a sourcemark structure put in source_info to mark
+       the end of @value expansion.  Also use such a structure for
+       @macro, replacing 'end_macro'.
+       Check number of values expansion number and error out if
+       there is more than MAX_MACRO_CALL_NESTING.
+       correct MAX_MACRO_CALL_NESTING name in warning message.
+
+       * tp/Texinfo/XS/parsetexi/Parsetexi.pm (parser),
+       tp/Texinfo/XS/parsetexi/Parsetexi.xs
+       (conf_set_MAX_MACRO_CALL_NESTING), tp/Texinfo/XS/parsetexi/conf.c
+       (conf_set_MAX_MACRO_CALL_NESTING, reset_conf),
+       tp/Texinfo/XS/parsetexi/macro.c (handle_macro): pass
+       MAX_MACRO_CALL_NESTING to the XS parser.  Use that value for the
+       number of macro call nesting allowed.
+       correct MAX_MACRO_CALL_NESTING name in warning message.
+
+       * tp/t/60macro.t: add recursive_call_in_rmacro to test for an infinite
+       recursion.
+
 2023-01-04  Patrice Dumas  <pertusus@free.fr>
 
        * .gitignore: replace tp/tests/included_lat*n1.texi by
diff --git a/tp/TODO b/tp/TODO
index 921de87825..7e97b81c6b 100644
--- a/tp/TODO
+++ b/tp/TODO
@@ -105,8 +105,9 @@ the context command stack.
  @end defun
 
 
-Recursive expansion of @value may lead to an infinite loop.  Wait for
-marksource to proceed.
+Recursive expansion of @value may lead to an infinite loop.  Using
+a stack as for macros seems to be the best, and using sourcemark
+for the end of the expansion. (done in perl parser).
  https://bugzilla.redhat.com/show_bug.cgi?id=744878
 
 
diff --git a/tp/Texinfo/ParserNonXS.pm b/tp/Texinfo/ParserNonXS.pm
index d3e5484fc5..6f97e0e581 100644
--- a/tp/Texinfo/ParserNonXS.pm
+++ b/tp/Texinfo/ParserNonXS.pm
@@ -149,6 +149,8 @@ my %parser_state_initialization = (
                               # as obtained by parsing the @macro
   'macro_stack' => [],        # stack of macros being expanded (more recent
                               # first)
+  'value_stack' => [],        # stack of values being expanded (more recent
+                              # first)
   'merged_indices' => {},     # the key is merged in the value
   'regions_stack' => [],      # a stack of regions commands elements (block
                               # region commands)
@@ -2190,12 +2192,22 @@ sub _next_text($$)
     my $input = $self->{'input'}->[0];
     if (@{$input->{'pending'}}) {
       my $new_text_and_info = shift @{$input->{'pending'}};
-      if ($new_text_and_info->[1] and $new_text_and_info->[1]->{'end_macro'}) {
-        delete $new_text_and_info->[1]->{'end_macro'};
-        my $top_macro = shift @{$self->{'macro_stack'}};
-        print STDERR "SHIFT MACRO_STACK(@{$self->{'macro_stack'}}):"
-          ." $top_macro->{'args'}->[0]->{'text'}\n"
-            if ($self->{'DEBUG'});
+      if ($new_text_and_info->[1] and $new_text_and_info->[1]->{'sourcemark'}) 
{
+        my $sourcemark = $new_text_and_info->[1]->{'sourcemark'};
+        delete $new_text_and_info->[1]->{'sourcemark'};
+        if ($sourcemark->{'type'} eq 'macro'
+            and $sourcemark->{'status'} eq 'end') {
+          my $top_macro = shift @{$self->{'macro_stack'}};
+          print STDERR "SHIFT MACRO_STACK(@{$self->{'macro_stack'}}):"
+            ." $top_macro->{'args'}->[0]->{'text'}\n"
+              if ($self->{'DEBUG'});
+        } elsif ($sourcemark->{'type'} eq 'value'
+                 and $sourcemark->{'status'} eq 'end') {
+          my $top_value = shift @{$self->{'value_stack'}};
+          print STDERR "SHIFT VALUE_STACK(@{$self->{'value_stack'}}):"
+            . "$top_value\n"
+              if ($self->{'DEBUG'});
+        }
       }
       # corresponds to (line, new source_info)
       return ($new_text_and_info->[0], $new_text_and_info->[1]);
@@ -4392,7 +4404,7 @@ sub _process_remaining_on_line($$$$)
       if ($self->{'MAX_MACRO_CALL_NESTING'}
           and scalar(@{$self->{'macro_stack'}}) > 
$self->{'MAX_MACRO_CALL_NESTING'}) {
         $self->_line_warn(sprintf(__(
-  "macro call nested too deeply (set MAX_NESTED_MACROS to override; current 
value %d)"),
+  "macro call nested too deeply (set MAX_MACRO_CALL_NESTING to override; 
current value %d)"),
                               $self->{'MAX_MACRO_CALL_NESTING'}), 
$source_info);
         goto funexit;
       }
@@ -4423,7 +4435,9 @@ sub _process_remaining_on_line($$$$)
       my $new_lines = _complete_line_nr($expanded_lines,
                        $source_info->{'line_nr'}, $source_info->{'file_name'},
                        $expanded_macro->{'args'}->[0]->{'text'}, 1);
-      $source_info->{'end_macro'} = 1;
+      $source_info->{'sourcemark'} = {'type' => 'macro',
+                      'info' => $expanded_macro->{'args'}->[0]->{'text'},
+                      'status' => 'end'};
       # first put the line that was interrupted by the macro call
       # on the input pending text with information stack
       if (! scalar(@{$self->{'input'}})) {
@@ -4451,12 +4465,29 @@ sub _process_remaining_on_line($$$$)
       if ($expanded_line =~ s/^{([\w\-][^\s{\\}~`\^+"<>|@]*)}//) {
         my $value = $1;
         if (exists($self->{'values'}->{$value})) {
-          $line = $self->{'values'}->{$value} . $expanded_line;
+          if ($self->{'MAX_MACRO_CALL_NESTING'}
+             and scalar(@{$self->{'value_stack'}}) > 
$self->{'MAX_MACRO_CALL_NESTING'}) {
+            $self->_line_warn(sprintf(__(
+  "value call nested too deeply (set MAX_MACRO_CALL_NESTING to override; 
current value %d)"),
+                              $self->{'MAX_MACRO_CALL_NESTING'}), 
$source_info);
+            $line = $expanded_line;
+            goto funexit;
+          }
+          unshift @{$self->{'value_stack'}}, $value;
+          if (! scalar(@{$self->{'input'}})) {
+            push @{$self->{'input'}}, {'pending' => []};
+          }
+          my $pending_source_info = { %$source_info };
+          $pending_source_info->{'sourcemark'} = {'type' => 'value',
+                                                  'info' => $value,
+                                                  'status' => 'end'};
+          unshift @{$self->{'input'}->[0]->{'pending'}},
+                                 [$expanded_line, $pending_source_info];
+          $line = $self->{'values'}->{$value};
           goto funexit;
         }
       }
     }
-      #substr($line, 0, $at_command_length) = '';
   }
 
   # special case for @-command as argument of @itemize or @*table.
diff --git a/tp/Texinfo/XS/parsetexi/Parsetexi.pm 
b/tp/Texinfo/XS/parsetexi/Parsetexi.pm
index 0dbb27ceeb..840fa89c6d 100644
--- a/tp/Texinfo/XS/parsetexi/Parsetexi.pm
+++ b/tp/Texinfo/XS/parsetexi/Parsetexi.pm
@@ -137,6 +137,8 @@ sub parser (;$$)
         conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME ($conf->{$key});
       } elsif ($key eq 'CPP_LINE_DIRECTIVES') {
         conf_set_CPP_LINE_DIRECTIVES($conf->{$key});
+      } elsif ($key eq 'MAX_MACRO_CALL_NESTING') {
+        conf_set_MAX_MACRO_CALL_NESTING($conf->{$key});
       } elsif ($key eq 'DEBUG') {
         set_debug($conf->{$key}) if $conf->{$key};
       } elsif ($key eq 'DOC_ENCODING_FOR_INPUT_FILE_NAME') {
diff --git a/tp/Texinfo/XS/parsetexi/Parsetexi.xs 
b/tp/Texinfo/XS/parsetexi/Parsetexi.xs
index d5972061fa..74ef870d14 100644
--- a/tp/Texinfo/XS/parsetexi/Parsetexi.xs
+++ b/tp/Texinfo/XS/parsetexi/Parsetexi.xs
@@ -106,6 +106,9 @@ conf_set_CPP_LINE_DIRECTIVES (int i)
 void
 conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME (int i)
 
+void
+conf_set_MAX_MACRO_CALL_NESTING (int i)
+
 void
 set_DOC_ENCODING_FOR_INPUT_FILE_NAME (int i)
 
diff --git a/tp/Texinfo/XS/parsetexi/conf.c b/tp/Texinfo/XS/parsetexi/conf.c
index 5797e12853..4d29326557 100644
--- a/tp/Texinfo/XS/parsetexi/conf.c
+++ b/tp/Texinfo/XS/parsetexi/conf.c
@@ -40,6 +40,12 @@ conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME (int i)
   conf.ignore_space_after_braced_command_name = i;
 }
 
+void
+conf_set_MAX_MACRO_CALL_NESTING (int i)
+{
+  conf.max_macro_call_nesting = i;
+}
+
 void
 reset_conf (void)
 {
@@ -47,5 +53,6 @@ reset_conf (void)
   conf.show_menu = 1;
   conf.cpp_line_directives = 1;
   conf.ignore_space_after_braced_command_name = 1;
+  conf.max_macro_call_nesting = 100000;
   conf.doc_encoding_for_input_file_name = 1;
 }
diff --git a/tp/Texinfo/XS/parsetexi/conf.h b/tp/Texinfo/XS/parsetexi/conf.h
index 33ce3b7fbf..9236ea7191 100644
--- a/tp/Texinfo/XS/parsetexi/conf.h
+++ b/tp/Texinfo/XS/parsetexi/conf.h
@@ -20,6 +20,7 @@ typedef struct CONF {
     int show_menu;
     int cpp_line_directives;
     int ignore_space_after_braced_command_name;
+    int max_macro_call_nesting;
     int doc_encoding_for_input_file_name;
 } CONF;
 
@@ -28,6 +29,7 @@ extern CONF conf;
 void conf_set_show_menu (int i);
 void conf_set_CPP_LINE_DIRECTIVES (int i);
 void conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME (int i);
+void conf_set_MAX_MACRO_CALL_NESTING (int i);
 void reset_conf (void);
 
 #endif
diff --git a/tp/Texinfo/XS/parsetexi/macro.c b/tp/Texinfo/XS/parsetexi/macro.c
index a24bb2fc7f..29d4900817 100644
--- a/tp/Texinfo/XS/parsetexi/macro.c
+++ b/tp/Texinfo/XS/parsetexi/macro.c
@@ -558,13 +558,14 @@ handle_macro (ELEMENT *current, char **line_inout, enum 
command_id cmd)
   if (expanded.end > 0 && expanded.text[expanded.end - 1] == '\n')
     expanded.text[--expanded.end] = '\0';
 
-  if (input_number >= 1000)
+  if (conf.max_macro_call_nesting
+      && input_number >= conf.max_macro_call_nesting)
     {
       line_warn (
          "macro call nested too deeply "
-         "(set MAX_NESTED_MACROS to override; current value %d)", 1000);
+         "(set MAX_MACRO_CALL_NESTING to override; current value %d)",
+                conf.max_macro_call_nesting);
       goto funexit;
-      /* TODO: actually check MAX_NESTED_MACROS? */
     }
 
   if (macro->cmd == CM_macro)
diff --git a/tp/t/60macro.t b/tp/t/60macro.t
index 0364cdbafe..80e05b1c3d 100644
--- a/tp/t/60macro.t
+++ b/tp/t/60macro.t
@@ -954,6 +954,17 @@ ggg
 fff
 @end macro
 @mac'],
+# takes long with default MAX_MACRO_CALL_NESTING value (tested with
+# pure perl Parser).
+['recursive_call_in_rmacro',
+'
+@rmacro rec
+@rec{}
+@end rmacro
+
+@rec{}
+
+', {'MAX_MACRO_CALL_NESTING' => 100}],
 ['unknown_macro_on_line_command',
 '@setfilename @begin{}file'
 ],
diff --git a/tp/t/results/macro/recursive_call_in_rmacro.pl 
b/tp/t/results/macro/recursive_call_in_rmacro.pl
new file mode 100644
index 0000000000..b07cb8e70c
--- /dev/null
+++ b/tp/t/results/macro/recursive_call_in_rmacro.pl
@@ -0,0 +1,124 @@
+use vars qw(%result_texis %result_texts %result_trees %result_errors 
+   %result_indices %result_sectioning %result_nodes %result_menus
+   %result_floats %result_converted %result_converted_errors 
+   %result_elements %result_directions_text %result_indices_sort_strings);
+
+use utf8;
+
+$result_trees{'recursive_call_in_rmacro'} = {
+  'contents' => [
+    {
+      'contents' => [
+        {
+          'text' => '
+',
+          'type' => 'empty_line'
+        },
+        {
+          'args' => [
+            {
+              'text' => 'rec',
+              'type' => 'macro_name'
+            }
+          ],
+          'cmdname' => 'rmacro',
+          'contents' => [
+            {
+              'text' => '@rec{}
+',
+              'type' => 'raw'
+            },
+            {
+              'args' => [
+                {
+                  'contents' => [
+                    {
+                      'text' => 'rmacro'
+                    }
+                  ],
+                  'info' => {
+                    'spaces_after_argument' => '
+'
+                  },
+                  'type' => 'line_arg'
+                }
+              ],
+              'cmdname' => 'end',
+              'extra' => {
+                'text_arg' => 'rmacro'
+              },
+              'info' => {
+                'spaces_before_argument' => ' '
+              },
+              'source_info' => {
+                'file_name' => '',
+                'line_nr' => 4,
+                'macro' => ''
+              }
+            }
+          ],
+          'info' => {
+            'arg_line' => ' rec
+'
+          },
+          'source_info' => {
+            'file_name' => '',
+            'line_nr' => 2,
+            'macro' => ''
+          }
+        },
+        {
+          'text' => '
+',
+          'type' => 'empty_line'
+        },
+        {
+          'text' => '
+',
+          'type' => 'empty_line'
+        },
+        {
+          'text' => '
+',
+          'type' => 'empty_line'
+        }
+      ],
+      'type' => 'before_node_section'
+    }
+  ],
+  'type' => 'document_root'
+};
+
+$result_texis{'recursive_call_in_rmacro'} = '
+@rmacro rec
+@rec{}
+@end rmacro
+
+
+
+';
+
+
+$result_texts{'recursive_call_in_rmacro'} = '
+
+
+
+';
+
+$result_errors{'recursive_call_in_rmacro'} = [
+  {
+    'error_line' => 'warning: macro call nested too deeply (set 
MAX_MACRO_CALL_NESTING to override; current value 100) (possibly involving @rec)
+',
+    'file_name' => '',
+    'line_nr' => 6,
+    'macro' => 'rec',
+    'text' => 'macro call nested too deeply (set MAX_MACRO_CALL_NESTING to 
override; current value 100)',
+    'type' => 'warning'
+  }
+];
+
+
+$result_floats{'recursive_call_in_rmacro'} = {};
+
+
+1;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]