diff options
Diffstat (limited to 'Build')
-rw-r--r-- | Build/source/texk/web2c/ChangeLog | 2 | ||||
-rw-r--r-- | Build/source/texk/web2c/NEWS | 3 | ||||
-rw-r--r-- | Build/source/texk/web2c/lib/ChangeLog | 9 | ||||
-rw-r--r-- | Build/source/texk/web2c/lib/texmfmp.c | 78 |
4 files changed, 84 insertions, 8 deletions
diff --git a/Build/source/texk/web2c/ChangeLog b/Build/source/texk/web2c/ChangeLog index cc416ac5111..92ff686754d 100644 --- a/Build/source/texk/web2c/ChangeLog +++ b/Build/source/texk/web2c/ChangeLog @@ -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 diff --git a/Build/source/texk/web2c/NEWS b/Build/source/texk/web2c/NEWS index de176de3280..4ec1756deed 100644 --- a/Build/source/texk/web2c/NEWS +++ b/Build/source/texk/web2c/NEWS @@ -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 diff --git a/Build/source/texk/web2c/lib/ChangeLog b/Build/source/texk/web2c/lib/ChangeLog index 07e89945c76..dc9219b043f 100644 --- a/Build/source/texk/web2c/lib/ChangeLog +++ b/Build/source/texk/web2c/lib/ChangeLog @@ -1,3 +1,12 @@ +2020-07-17 Karl Berry <karl@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@w32tex.org> * printversion.c: Update copyright year. diff --git a/Build/source/texk/web2c/lib/texmfmp.c b/Build/source/texk/web2c/lib/texmfmp.c index 10fd2846cd7..eadaa85e468 100644 --- a/Build/source/texk/web2c/lib/texmfmp.c +++ b/Build/source/texk/web2c/lib/texmfmp.c @@ -2564,7 +2564,7 @@ calledit (packedASCIIcode *filename, { 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 @@ calledit (packedASCIIcode *filename, 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"); -#endif + 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 @@ calledit (packedASCIIcode *filename, 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 @@ calledit (packedASCIIcode *filename, { if (c == '%') { + int i; switch (c = *edit_value++) { case 'd': |