texinfo-commits
[Top][All Lists]
Advanced

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

branch master updated: * tp/Texinfo/XS/parsetexi/input.c (input_push), t


From: Patrice Dumas
Subject: branch master updated: * tp/Texinfo/XS/parsetexi/input.c (input_push), tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): pass expanded value and put in value_flag in input structure. Update callers. * tp/Texinfo/XS/parsetexi/input.c (macro_expansion_nr) (value_expansion_nr, next_text), tp/Texinfo/XS/parsetexi/macro.c (handle_macro), tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): use separate counters for values and macros expansions.
Date: Sat, 07 Jan 2023 17:37:48 -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 655e78aa6e * tp/Texinfo/XS/parsetexi/input.c (input_push), 
tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): pass expanded 
value and put in value_flag in input structure.  Update callers. * 
tp/Texinfo/XS/parsetexi/input.c (macro_expansion_nr) (value_expansion_nr, 
next_text), tp/Texinfo/XS/parsetexi/macro.c (handle_macro), 
tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): use separate 
counters for values and macros expansions.
655e78aa6e is described below

commit 655e78aa6e7846c65c9d23c3ea7b56880a78a421
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Sat Jan 7 23:35:47 2023 +0100

    * tp/Texinfo/XS/parsetexi/input.c (input_push),
    tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): pass
    expanded value and put in value_flag in input structure.  Update
    callers.
    * tp/Texinfo/XS/parsetexi/input.c (macro_expansion_nr)
    (value_expansion_nr, next_text), tp/Texinfo/XS/parsetexi/macro.c
    (handle_macro), tp/Texinfo/XS/parsetexi/parser.c
    (process_remaining_on_line): use separate counters for values and
    macros expansions.
    
    * tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): error
    out on value expansion number higher than MAX_MACRO_CALL_NESTING.
    
    * tp/Texinfo/ParserNonXS.pm (_input_push, _process_remaining_on_line):
    put expanded value in iput.  Use 'value_flag' for value flag key name
    in input.
    
    * tp/Texinfo/ParserNonXS.pm (_input_push, _next_text): fix conditions
    on macro being set.
    
    * tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): free
    value flag even if there was no value expansion.
    
    * tp/t/50value.t: add recursive_expansion_in_set for a test of infinite
    recursion with @value.
---
 ChangeLog                                 | 28 ++++++++++++++++++++
 tp/TODO                                   |  7 ++---
 tp/Texinfo/ParserNonXS.pm                 | 42 ++++++++++++++----------------
 tp/Texinfo/XS/parsetexi/api.c             |  6 ++---
 tp/Texinfo/XS/parsetexi/handle_commands.c |  2 +-
 tp/Texinfo/XS/parsetexi/input.c           | 20 +++++++++++---
 tp/Texinfo/XS/parsetexi/input.h           |  4 ++-
 tp/Texinfo/XS/parsetexi/macro.c           |  7 ++---
 tp/Texinfo/XS/parsetexi/parser.c          | 43 +++++++++++++++++++++----------
 tp/t/50value.t                            |  4 +++
 10 files changed, 111 insertions(+), 52 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 68f9df77af..b7c3591444 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2023-01-07  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/XS/parsetexi/input.c (input_push),
+       tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): pass
+       expanded value and put in value_flag in input structure.  Update
+       callers.
+       * tp/Texinfo/XS/parsetexi/input.c (macro_expansion_nr)
+       (value_expansion_nr, next_text), tp/Texinfo/XS/parsetexi/macro.c
+       (handle_macro), tp/Texinfo/XS/parsetexi/parser.c
+       (process_remaining_on_line): use separate counters for values and
+       macros expansions.
+
+       * tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): error
+       out on value expansion number higher than MAX_MACRO_CALL_NESTING.
+
+       * tp/Texinfo/ParserNonXS.pm (_input_push, _process_remaining_on_line):
+       put expanded value in iput.  Use 'value_flag' for value flag key name
+       in input.
+
+       * tp/Texinfo/ParserNonXS.pm (_input_push, _next_text): fix conditions
+       on macro being set.
+
+       * tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line): free
+       value flag even if there was no value expansion.
+
+       * tp/t/50value.t: add recursive_expansion_in_set for a test of infinite
+       recursion with @value.
+
 2023-01-07  Gavin Smith  <gavinsmith0123@gmail.com>
 
        Treat spaces in @verb and @w differently in HTML
diff --git a/tp/TODO b/tp/TODO
index e4a24badfa..accc935612 100644
--- a/tp/TODO
+++ b/tp/TODO
@@ -16,6 +16,8 @@ Bugs
 test with cpp directive in macro, verify that file name is stil changed
 after the macro expansion
 
+on the same line as a macro expansion check the source_info, incorrect macro?
+
 HTML API
 ========
 
@@ -108,11 +110,6 @@ the context command stack.
  @end defun
 
 
-Recursive expansion of @value may lead to an infinite loop.  Fixed in
-pure perl parser, still to be done in XS parser.
- https://bugzilla.redhat.com/show_bug.cgi?id=744878
-
-
 In HTML, some @-commands do not have an element with a class associated, or the
 association is not perfect.  There is @author in @quotation, @-command affected
 by @definfoenclose.  @pxref and similar @-commands have no class for references
diff --git a/tp/Texinfo/ParserNonXS.pm b/tp/Texinfo/ParserNonXS.pm
index 9d343df133..b78f8d0446 100644
--- a/tp/Texinfo/ParserNonXS.pm
+++ b/tp/Texinfo/ParserNonXS.pm
@@ -792,7 +792,6 @@ sub _input_push($$$;$$)
 {
   my ($self, $text, $line_nr, $macro_name, $value_name) = @_;
 
-  my $filename;
   if (not $self->{'input'}) {
     $self->{'input'} = [];
   }
@@ -802,16 +801,15 @@ sub _input_push($$$;$$)
     $input_source_info->{'file_name'}
       = $self->{'input'}->[0]->{'input_source_info'}->{'file_name'};
   }
-  if (defined($macro_name)) {
+  if (defined($macro_name) and $macro_name ne '') {
     $input_source_info->{'macro'} = $macro_name;
   } elsif (not defined($value_name)) {
     # this counteracts the increment that would follow from the next
     # call to _next_text.
     $input_source_info->{'line_nr'} -= 1;
   }
-  $input_source_info->{'file_name'} = $filename if (defined($filename));
   my $text_input = _new_text_input($text, $input_source_info);
-  $text_input->{'expanded_value'} = 1 if (defined($value_name));
+  $text_input->{'value_flag'} = $value_name if (defined($value_name));
   unshift @{$self->{'input'}}, $text_input;
 }
 
@@ -1045,10 +1043,6 @@ sub _setup_conf($$)
   if (defined($conf)) {
     foreach my $key (keys(%$conf)) {
       if (exists($parser_settable_configuration{$key})) {
-        #if ($key eq 'info') {
-        #  # merge hashes prefering values from $conf
-        #  $parser->{'info'} = { %{$parser->{'info'}}, %{$conf->{'info'}} };
-        #}
         # we keep registrar instead of copying on purpose, to reuse the object
         if ($key ne 'values' and $key ne 'registrar' and ref($conf->{$key})) {
           $parser->{$key} = dclone($conf->{$key});
@@ -1493,7 +1487,7 @@ sub _in_paragraph($$)
   }
 }
 
-# close brace commands, that don't set a new context (ie @caption, @footnote)
+# close brace commands that don't set a new context (ie not @caption, 
@footnote)
 sub _close_all_style_commands($$$;$$)
 {
   my ($self, $current, $source_info, $closed_block_command,
@@ -2197,12 +2191,12 @@ sub _next_text($)
       my $texthandle = $input->{'th'};
       my $next_line = <$texthandle>;
       if (!defined($next_line)) {
-        if ($input->{'input_source_info'}->{'macro'}) {
+        if ($input->{'input_source_info'}->{'macro'} ne '') {
           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 ($input->{'expanded_value'}) {
+        } elsif (defined($input->{'value_flag'})) {
           my $top_value = shift @{$self->{'value_stack'}};
           print STDERR "SHIFT VALUE_STACK(@{$self->{'value_stack'}}):"
             . "$top_value\n"
@@ -2212,8 +2206,8 @@ sub _next_text($)
         # need to decode to characters
         $next_line = Encode::decode('utf8', $next_line);
         $input->{'input_source_info'}->{'line_nr'} += 1
-          unless ($input->{'input_source_info'}->{'macro'}
-                  or $input->{'expanded_value'});
+          unless ($input->{'input_source_info'}->{'macro'} ne ''
+                  or defined($input->{'value_flag'}));
         return ($next_line, { %{$input->{'input_source_info'}} });
       }
     } elsif ($input->{'fh'}) {
@@ -4423,7 +4417,7 @@ sub _process_remaining_on_line($$$$)
         goto funexit;
       }
       if ($self->{'MAX_MACRO_CALL_NESTING'}
-          and scalar(@{$self->{'macro_stack'}}) > 
$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_MACRO_CALL_NESTING to override; 
current value %d)"),
                               $self->{'MAX_MACRO_CALL_NESTING'}), 
$source_info);
@@ -4466,26 +4460,28 @@ sub _process_remaining_on_line($$$$)
     # which may need a well formed tree, which is not needed here, and
     # early value expansion may be needed to provide with an argument.
     if ($command eq 'value') {
-      my $expanded_line = $line;
-      substr($expanded_line, 0, $at_command_length) = '';
-      $expanded_line =~ s/^\s*//
+      my $remaining_line = $line;
+      substr($remaining_line, 0, $at_command_length) = '';
+      $remaining_line =~ s/^\s*//
          if ($self->{'IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME'});
       # REVALUE
-      if ($expanded_line =~ s/^{([\w\-][^\s{\\}~`\^+"<>|@]*)}//) {
+      if ($remaining_line =~ s/^{([\w\-][^\s{\\}~`\^+"<>|@]*)}//) {
         my $value = $1;
         if (exists($self->{'values'}->{$value})) {
           if ($self->{'MAX_MACRO_CALL_NESTING'}
-             and scalar(@{$self->{'value_stack'}}) > 
$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;
+            $line = $remaining_line;
             goto funexit;
           }
           unshift @{$self->{'value_stack'}}, $value;
-          _input_push($self, $expanded_line, $source_info->{'line_nr'},
-                      $source_info->{'macro'}, $value);
-          $line = $self->{'values'}->{$value};
+          _input_push($self, $remaining_line, $source_info->{'line_nr'},
+                      $source_info->{'macro'});
+          _input_push($self, $self->{'values'}->{$value},
+                      $source_info->{'line_nr'}, $source_info->{'macro'}, 
$value);
+          $line = '';
           goto funexit;
         }
       }
diff --git a/tp/Texinfo/XS/parsetexi/api.c b/tp/Texinfo/XS/parsetexi/api.c
index 08041b26e6..04aa654906 100644
--- a/tp/Texinfo/XS/parsetexi/api.c
+++ b/tp/Texinfo/XS/parsetexi/api.c
@@ -212,7 +212,7 @@ void
 parse_text (char *string, int line_nr)
 {
   reset_parser_except_conf ();
-  input_push (strdup (string), line_nr, 0);
+  input_push (strdup (string), line_nr, 0, 0);
   Root = parse_texi_document ();
 }
 
@@ -224,7 +224,7 @@ parse_string (char *string, int line_nr)
   ELEMENT *root_elt = new_element (ET_root_line);
 
   reset_parser_except_conf ();
-  input_push (strdup (string), line_nr, 0);
+  input_push (strdup (string), line_nr, 0, 0);
   Root = parse_texi (root_elt, root_elt);
 }
 
@@ -236,7 +236,7 @@ parse_piece (char *string, int line_nr)
   ELEMENT *document_root = before_node_section->parent;
 
   reset_parser_except_conf ();
-  input_push (strdup (string), line_nr, 0);
+  input_push (strdup (string), line_nr, 0, 0);
   Root = parse_texi (document_root, before_node_section);
 }
 
diff --git a/tp/Texinfo/XS/parsetexi/handle_commands.c 
b/tp/Texinfo/XS/parsetexi/handle_commands.c
index 8dfdcc1ba1..2406096cf3 100644
--- a/tp/Texinfo/XS/parsetexi/handle_commands.c
+++ b/tp/Texinfo/XS/parsetexi/handle_commands.c
@@ -353,7 +353,7 @@ handle_line_command (ELEMENT *current, char **line_inout,
           char *line2;
           SOURCE_INFO save_src_info; 
 
-          input_push (strdup (line), current_source_info.line_nr, 0);
+          input_push (strdup (line), current_source_info.line_nr, 0, 0);
 
           save_src_info = current_source_info;
           line2 = new_line ();
diff --git a/tp/Texinfo/XS/parsetexi/input.c b/tp/Texinfo/XS/parsetexi/input.c
index e8cd70fce5..45fa5d12ad 100644
--- a/tp/Texinfo/XS/parsetexi/input.c
+++ b/tp/Texinfo/XS/parsetexi/input.c
@@ -48,6 +48,8 @@ typedef struct {
     char *text;  /* Input text to be parsed as Texinfo. */
     char *ptext; /* How far we are through 'text'.  Used to split 'text'
                     into lines. */
+    char *value_flag; /* value flag if the input text is a @value
+                         explansion */
 } INPUT;
 
 static char *input_pushback_string;
@@ -90,6 +92,8 @@ set_input_encoding (char *encoding)
 static INPUT *input_stack = 0;
 int input_number = 0;
 int input_space = 0;
+int macro_expansion_nr = 0;
+int value_expansion_nr = 0;
 
 /* Current filename and line number.  Used for reporting. */
 SOURCE_INFO current_source_info;
@@ -412,6 +416,13 @@ next_text (void)
             {
               /* End of text reached. */
               free (i->text);
+              if (i->value_flag)
+                {
+                  value_expansion_nr--;
+                  free (i->value_flag);
+                }
+              else if (i->source_info.macro)
+                macro_expansion_nr--;
               break;
             }
           /* Split off a line of input. */
@@ -422,7 +433,7 @@ next_text (void)
           else
             i->ptext = p; /* The next time, we will pop the input source. */
 
-          if (!i->source_info.macro)
+          if (!i->source_info.macro && !i->value_flag)
             i->source_info.line_nr++;
 
           current_source_info = i->source_info;
@@ -485,7 +496,7 @@ next_text (void)
    string.  TEXT will be later free'd and must be allocated on the heap.
    MACRO is the name of a macro that the text came from. */
 void
-input_push (char *text, int line_number, char *macro)
+input_push (char *text, int line_number, char *macro, char *value_flag)
 {
   char *filename = 0;
 
@@ -505,7 +516,7 @@ input_push (char *text, int line_number, char *macro)
   input_stack[input_number].text = text;
   input_stack[input_number].ptext = text;
 
-  if (!macro)
+  if (!macro && !value_flag)
     line_number--;
   input_stack[input_number].source_info.line_nr = line_number;
   if (input_number > 0)
@@ -514,6 +525,7 @@ input_push (char *text, int line_number, char *macro)
     }
   input_stack[input_number].source_info.file_name = save_string (filename);
   input_stack[input_number].source_info.macro = save_string (macro);
+  input_stack[input_number].value_flag = value_flag;
   input_number++;
 }
 
@@ -574,6 +586,8 @@ input_reset_input_stack (void)
         }
     }
   input_number = 0;
+  macro_expansion_nr = 0;
+  value_expansion_nr = 0;
 }
 
 int
diff --git a/tp/Texinfo/XS/parsetexi/input.h b/tp/Texinfo/XS/parsetexi/input.h
index 5f18222e33..ba13ca42a0 100644
--- a/tp/Texinfo/XS/parsetexi/input.h
+++ b/tp/Texinfo/XS/parsetexi/input.h
@@ -9,7 +9,7 @@ char *next_text (void);
 
 void save_line_directive (int line_nr, char *filename);
 
-void input_push (char *text, int line_number, char *macro);
+void input_push (char *text, int line_number, char *macro, char *value_flag);
 int input_push_file (char *filename);
 void input_pushback (char *line);
 void input_reset_input_stack (void);
@@ -28,6 +28,8 @@ void free_small_strings (void);
 extern SOURCE_INFO current_source_info;
 
 extern int input_number;
+extern int macro_expansion_nr;
+extern int value_expansion_nr;
 
 extern int doc_encoding_for_input_file_name;
 extern char *input_file_name_encoding;
diff --git a/tp/Texinfo/XS/parsetexi/macro.c b/tp/Texinfo/XS/parsetexi/macro.c
index 8c9de1ab4e..efe142ce14 100644
--- a/tp/Texinfo/XS/parsetexi/macro.c
+++ b/tp/Texinfo/XS/parsetexi/macro.c
@@ -559,7 +559,7 @@ handle_macro (ELEMENT *current, char **line_inout, enum 
command_id cmd)
     expanded.text[--expanded.end] = '\0';
 
   if (conf.max_macro_call_nesting
-      && input_number >= conf.max_macro_call_nesting)
+      && macro_expansion_nr >= conf.max_macro_call_nesting)
     {
       line_warn (
          "macro call nested too deeply "
@@ -594,9 +594,10 @@ handle_macro (ELEMENT *current, char **line_inout, enum 
command_id cmd)
   // 3958 Pop macro stack
 
   /* Put expansion in front of the current line. */
-  input_push (strdup (line), current_source_info.line_nr, 0);
+  macro_expansion_nr++;
+  input_push (strdup (line), current_source_info.line_nr, 0, 0);
   line = strchr (line, '\0');
-  input_push (expanded.text, current_source_info.line_nr, command_name(cmd));
+  input_push (expanded.text, current_source_info.line_nr, command_name(cmd), 
0);
 
 funexit:
   *line_inout = line;
diff --git a/tp/Texinfo/XS/parsetexi/parser.c b/tp/Texinfo/XS/parsetexi/parser.c
index 65c15b7f1d..7039f98a6a 100644
--- a/tp/Texinfo/XS/parsetexi/parser.c
+++ b/tp/Texinfo/XS/parsetexi/parser.c
@@ -1553,41 +1553,58 @@ superfluous_arg:
      and early value expansion may be needed to provide with an argument. */
   else if (cmd == CM_value)
     {
-      char *expanded_line = line_after_command;
+      char *remaining_line = line_after_command;
       if (conf.ignore_space_after_braced_command_name)
-        expanded_line += strspn (expanded_line, whitespace_chars);
-      if (*expanded_line == '{')
+        remaining_line += strspn (remaining_line, whitespace_chars);
+      if (*remaining_line == '{')
         {
           char *flag;
 
-          expanded_line++;
-          flag = read_flag_name (&expanded_line);
+          remaining_line++;
+          flag = read_flag_name (&remaining_line);
           if (flag)
             {
-              if (*expanded_line == '}')
+              if (*remaining_line == '}')
                 {
                   char *value;
                   value = fetch_value (flag);
 
                   if (value)
                     {
-                      expanded_line++; /* past '}' */
-                      input_push (strdup (expanded_line),
+                      remaining_line++; /* past '}' */
+                      if (conf.max_macro_call_nesting
+                          && value_expansion_nr >= conf.max_macro_call_nesting)
+                        {
+                          line_warn (
+                            "value call nested too deeply "
+                            "(set MAX_MACRO_CALL_NESTING to override; current 
value %d)",
+                             conf.max_macro_call_nesting);
+                          free (flag);
+                          line = remaining_line;
+                          goto funexit;
+                        }
+
+                      input_push (strdup (remaining_line),
                                   current_source_info.line_nr,
-                                  current_source_info.macro);
+                                  current_source_info.macro, 0);
                       input_push (strdup (value),
                                   current_source_info.line_nr,
-                                  current_source_info.macro);
+                                  current_source_info.macro,
+                                  strdup(flag));
+                      value_expansion_nr++;
 
                       /* Move 'line' to end of string so next input to
                          be processed is taken from input stack. */
-                      line = expanded_line + strlen (expanded_line);
+                      line = remaining_line + strlen (remaining_line);
                       retval = STILL_MORE_TO_PROCESS;
                     }
-                  free (flag);
                   if (value)
-                    goto funexit;
+                    {
+                      free (flag);
+                      goto funexit;
+                    }
                 }
+              free (flag);
             }
         }
     }
diff --git a/tp/t/50value.t b/tp/t/50value.t
index ba5e4c4816..678e661400 100644
--- a/tp/t/50value.t
+++ b/tp/t/50value.t
@@ -61,6 +61,10 @@ Value
 @value{myspace} 
 1
 '],
+['recursive_expansion_in_set',
+'@set V @value{V}
+@value{V}
+', {'MAX_MACRO_CALL_NESTING' => 100}],
 ['value_in_node',
 '@set node1 Node 1
 



reply via email to

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