Ivan Krylov
2019-Dec-15 16:41 UTC
[Rd] system2 doesn't quote stdin on unix, unlike stdout, stderr & input and on Windows
Hi again! While investigating the bug report [*] I found out that on unix, system2 does not quote its `stdin` argument while preparing the command line to launch. It does shQuote the `stdout` and `stderr` arguments, and also the `f <- tmpfile()` variable (which is used if `input` argument is provided), which seems to set a precedent. On Windows, stdin, stdout, and stderr are handled independently of the shell, so it also just works without the use of shQuote by the caller. Have people been relying on system2 not quoting the `stdin` argument, but quoting `stdout` and `stderr`? For what it's worth, neither R_runR in src/library/tools/R/check.R, nor .system_with_capture in src/library/tools/R/utils.R (the only callers of system2(..., stdin = ...)), nor their callers seem to be shQuote'ing the `stdin` argument. Nor the rare system2(..., stdin = ...) callers (or their callers) on CRAN seem to be quoting the `stdin` argument (I did find one exception [**]), it usually being "" or tmpfile() passed across a few function calls. Given the considerations above, would the following patch be a good idea? Index: src/library/base/R/unix/system.unix.R ==================================================================--- src/library/base/R/unix/system.unix.R (revision 77566) +++ src/library/base/R/unix/system.unix.R (working copy) @@ -102,7 +102,7 @@ writeLines(input, f) ## here 'command' is a single command, unlike system() command <- paste(command, "<", shQuote(f)) - } else if (nzchar(stdin)) command <- paste(command, "<", stdin) + } else if (nzchar(stdin)) command <- paste(command, "<", shQuote(stdin)) if(!wait && !intern) command <- paste(command, "&") .Internal(system(command, intern, timeout)) } -- Best regards, Ivan [*] https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17673 [**] https://github.com/search?q=org%3Acran+system2%28+stdin&type=Code The search is probably computationally expensive and thus might only be available to GitHub account holders. The results are: - BatchJobs: R/WorkerLinux.R; stdin is "" by default, filenames generated by cfBrewTemplate aren't quoted - batchtools: callers of runOSCommand actually quote the stdin argument! https://github.com/mllg/batchtools/commit/4a5818d70c82c8842c0b8bded224dbb423b79f33 - nat: R/cmtk.R, R/xformpoints.R; stdin is tempfile(...) - credentials: R/credential-api.R; stdin is passed as-is, tempfile() or "" in default arguments - runjags: R/setup.jags.jagsfile.R; stdin is constant "script.cmd" - m2r: R/m2.R; stdin is constant "" - scriptexec: R/scriptexec.R; stdin is passed as-is or default value retained - BioInstaller: inst/extdata/shiny/global_var.R; stdin is "" by default and passed as-is, callers of the sql2sqlite function don't quote the sql.file argument - annovarR: R/build.R: same sql2sqlite function as above
Tomas Kalibera
2019-Dec-17 16:38 UTC
[Rd] system2 doesn't quote stdin on unix, unlike stdout, stderr & input and on Windows
Thank you for the report, I agree that system2() should quote stdin. It will be a change in behavior that is observable, but not documented (so users/programs should not depend on it) and in addition seems to be a bug. I'll still test on CRAN+BIOC packages, together with your patches for PR17673. Best, Tomas On 12/15/19 5:41 PM, Ivan Krylov wrote:> Hi again! > > While investigating the bug report [*] I found out that on unix, system2 > does not quote its `stdin` argument while preparing the command line to launch. > > It does shQuote the `stdout` and `stderr` arguments, and also the `f <- > tmpfile()` variable (which is used if `input` argument is provided), > which seems to set a precedent. On Windows, stdin, stdout, and stderr are handled independently of the shell, so it also just works without the use of shQuote by the caller. > > Have people been relying on system2 not quoting the `stdin` argument, but > quoting `stdout` and `stderr`? For what it's worth, neither R_runR in > src/library/tools/R/check.R, nor .system_with_capture in > src/library/tools/R/utils.R (the only callers of system2(..., stdin = ...)), > nor their callers seem to be shQuote'ing the `stdin` argument. > > Nor the rare system2(..., stdin = ...) callers (or their callers) on CRAN > seem to be quoting the `stdin` argument (I did find one exception [**]), it usually being "" or tmpfile() passed across a few function calls. > > Given the considerations above, would the following patch be a good idea? > > Index: src/library/base/R/unix/system.unix.R > ==================================================================> --- src/library/base/R/unix/system.unix.R (revision 77566) > +++ src/library/base/R/unix/system.unix.R (working copy) > @@ -102,7 +102,7 @@ > writeLines(input, f) > ## here 'command' is a single command, unlike system() > command <- paste(command, "<", shQuote(f)) > - } else if (nzchar(stdin)) command <- paste(command, "<", stdin) > + } else if (nzchar(stdin)) command <- paste(command, "<", shQuote(stdin)) > if(!wait && !intern) command <- paste(command, "&") > .Internal(system(command, intern, timeout)) > } >