texlive[55857] Build/source/texk/web2c: avoid seg fault if e(dit) in

commits+karl at tug.org commits+karl at tug.org
Fri Jul 17 18:43:20 CEST 2020


Revision: 55857
          http://tug.org/svn/texlive?view=revision&revision=55857
Author:   karl
Date:     2020-07-17 18:43:20 +0200 (Fri, 17 Jul 2020)
Log Message:
-----------
avoid seg fault if e(dit) in middle of erroneous interaction

Modified Paths:
--------------
    trunk/Build/source/texk/web2c/ChangeLog
    trunk/Build/source/texk/web2c/NEWS
    trunk/Build/source/texk/web2c/lib/ChangeLog
    trunk/Build/source/texk/web2c/lib/texmfmp.c

Modified: trunk/Build/source/texk/web2c/ChangeLog
===================================================================
--- trunk/Build/source/texk/web2c/ChangeLog	2020-07-17 13:13:57 UTC (rev 55856)
+++ trunk/Build/source/texk/web2c/ChangeLog	2020-07-17 16:43:20 UTC (rev 55857)
@@ -20,7 +20,7 @@
 	call in unusual interactive sequences can mess up
 	the selector value, ultimately causing a segmentation fault
 	from writing to a closed stream \write15. Fix primarily
-	from David Fuchs.
+	from David Fuchs. Original report from Xiao Zhang,
 	https://tex.stackexchange.com/questions/551313/
 	https://tug.org/pipermail/tex-live/2020-June/045876.html
 

Modified: trunk/Build/source/texk/web2c/NEWS
===================================================================
--- trunk/Build/source/texk/web2c/NEWS	2020-07-17 13:13:57 UTC (rev 55856)
+++ trunk/Build/source/texk/web2c/NEWS	2020-07-17 16:43:20 UTC (rev 55857)
@@ -1,5 +1,8 @@
 This file records noteworthy changes.  (Public domain.)
 
+* obscure interaction sequences try to avoid crashing.
+
+

 2020 (for TeX Live 2020, 27 March 2020)
 * \input now also accepts a group-delimited filename, e.g.,
 \input{foo.tex}. The usage with a standard space/token-delimited

Modified: trunk/Build/source/texk/web2c/lib/ChangeLog
===================================================================
--- trunk/Build/source/texk/web2c/lib/ChangeLog	2020-07-17 13:13:57 UTC (rev 55856)
+++ trunk/Build/source/texk/web2c/lib/ChangeLog	2020-07-17 16:43:20 UTC (rev 55857)
@@ -1,3 +1,12 @@
+2020-07-17  Karl Berry  <karl at freefriends.org>
+
+	* texmfmp.c (calledit): close only open input files,
+	not non-files resulting from terminal interactions.
+	This means looking at each element of input_stack
+	instead of only looking at the input_file array. Painful.
+	Original report from Xiao Zhang,
+	https://tex.stackexchange.com/q/552113
+
 2020-01-01  Akira Kakuto  <kakuto at w32tex.org>
 
 	* printversion.c: Update copyright year.

Modified: trunk/Build/source/texk/web2c/lib/texmfmp.c
===================================================================
--- trunk/Build/source/texk/web2c/lib/texmfmp.c	2020-07-17 13:13:57 UTC (rev 55856)
+++ trunk/Build/source/texk/web2c/lib/texmfmp.c	2020-07-17 16:43:20 UTC (rev 55857)
@@ -2564,7 +2564,7 @@
 {
   char *temp, *command, *fullcmd;
   char c;
-  int sdone, ddone, i;
+  int sdone, ddone;
 
 #ifdef WIN32
   char *fp, *ffp, *env, editorname[256], buffer[256];
@@ -2575,13 +2575,76 @@
   sdone = ddone = 0;
   filename += fnstart;
 
-  /* Close any open input files, since we're going to kill the job.  */
-  for (i = 1; i <= inopen; i++)
+  /* Close any open input files, since we're going to kill the job and
+     the editor might well want to open them for writing.  On Windows,
+     at least, that would not be allowed when the file is still open.
+     
+     Unfortunately, the input_file array contains both the open files
+     that we want to close, and junk references to non-files for
+     terminal interaction that we must not try to close.  For example,
+     consider this input sequence:
+       \input test % contains a single line \bla, that is, any undefined cs
+       i\bum x     % insert another undefined control sequence
+       e           % invoke the editor
+     At this point input_file will have an open file for test.tex,
+     and a non-file for the insert. https://tex.stackexchange.com/q/552113 
+     
+     Therefore, we have to traverse down input_stack (not input_file),
+     looking for name_field values >17, which correspond to open
+     files, and then the index_field value of that entry tells us the
+     corresponding element of input_file, which is what we need to close.
+
+     We test for >17 because name_field=0 means the terminal,
+     name_field=1..16 means \openin stream n - 1,
+     name_field=17 means an invalid stream number (for read_toks).
+     Although ... seems like we should close any opened \openin files also.
+     Whoever is reading this, please implement that? Sigh.
+     
+     Description in modules 300--304 of tex.web: "Input stacks and states."
+     
+     Here, we do not have to look at cur_input, the global variable
+     which is effectively the top of input_stack, because it will always
+     be a terminal (non-file) interaction -- the one where the user
+     typed "e" to start the edit.  */
+ {  
+  int is_ptr; /* element of input_stack, 0 < input_ptr */  
+  for (is_ptr = 0; is_ptr < inputptr; is_ptr++) {
+    if (inputstack[is_ptr].namefield <= 17) {
+        ; /* fprintf (stderr, "calledit: skipped input_stack[%d], ", is_ptr);
+             fprintf (stderr, "namefield=%d <= 17\n",
+                      inputstack[is_ptr].namefield); */
+    } else {
+      FILE *f;
+      /* when name_field > 17, index_field specifies the element of
+         the input_file array, 1 <= in_open */
+      int if_ptr = inputstack[is_ptr].indexfield;
+      if (if_ptr < 1 || if_ptr > inopen) {
+      fprintf (stderr, "%s:calledit: unexpected if_ptr=%d not in range 1..%d,",
+                 argv[0], if_ptr, inopen);
+        fprintf (stderr, "from input_stack[%d].namefield=%d\n",
+                 is_ptr, inputstack[is_ptr].namefield);
+        exit (1);
+      }
+      
 #ifdef XeTeX
-    xfclose (inputfile[i]->f, "inputfile");
+      f = inputfile[if_ptr]->f;
 #else
-    xfclose (inputfile[i], "inputfile");
+      f = inputfile[if_ptr];
 #endif
+       /* fprintf (stderr,"calledit: input_stack #%d -> input_file #%d = %x\n",
+                   is_ptr, if_ptr, f); */
+      /* Although it should never happen, if the file value happens to
+         be zero, let's not gratuitously abort.  */
+      if (f) {
+        xfclose (f, "inputfile");
+      } else {
+        fprintf (stderr, "%s:calledit: not closing unexpected zero", argv[0]);
+        fprintf (stderr, " input_file[%d] from input_stack[%d].namefield=%d\n",
+                 if_ptr, is_ptr, inputstack[is_ptr].namefield);        
+      }
+    } /* end name_field > 17 */
+  }   /* end for loop for input_stack */
+ }    /* end block for variable declarations */
 
   /* Replace the default with the value of the appropriate environment
      variable or config file value, if it's set.  */
@@ -2590,7 +2653,7 @@
     edit_value = temp;
 
   /* Construct the command string.  The `11' is the maximum length an
-     integer might be.  */
+     integer might be (64 bits).  */
   command = xmalloc (strlen (edit_value) + fnlength + 11);
 
   /* So we can construct it as we go.  */
@@ -2611,6 +2674,7 @@
     {
       if (c == '%')
         {
+          int i;
           switch (c = *edit_value++)
             {
 	    case 'd':



More information about the tex-live-commits mailing list.