From 476310415a540abe3085cee48a35823eb668b634 Mon Sep 17 00:00:00 2001 From: Alex Vong Date: Fri, 24 Jun 2022 16:52:06 +0000 Subject: [PATCH 1/2] make_temp_file__: New function. Try to create temporary file in the most secure and portable way possible. Partially fixes #1145. * inst/make_temp_file__.m: New function. * inst/@sym/sym.m: Use it. * inst/private/python_ipc_system.m: Use it. --- inst/@sym/sym.m | 3 +- inst/make_temp_file__.m | 78 ++++++++++++++++++++++++++++++++ inst/private/python_ipc_system.m | 6 ++- 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 inst/make_temp_file__.m diff --git a/inst/@sym/sym.m b/inst/@sym/sym.m index 90a4a395b..31e44d567 100644 --- a/inst/@sym/sym.m +++ b/inst/@sym/sym.m @@ -1,5 +1,6 @@ %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% Copyright (C) 2016 Lagu +%% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% @@ -953,7 +954,7 @@ %! syms x %! y = 2*x; %! a = 42; -%! myfile = tempname (); +%! [fd, myfile] = make_temp_file__ (tempdir (), 'octsympy-myfile-'); %! save (myfile, 'x', 'y', 'a') %! clear x y a %! load (myfile) diff --git a/inst/make_temp_file__.m b/inst/make_temp_file__.m new file mode 100644 index 000000000..67a0fd7bc --- /dev/null +++ b/inst/make_temp_file__.m @@ -0,0 +1,78 @@ +%% Copyright (C) 2022 Alex Vong +%% +%% This file is part of OctSymPy. +%% +%% OctSymPy is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published +%% by the Free Software Foundation; either version 3 of the License, +%% or (at your option) any later version. +%% +%% This software is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty +%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +%% the GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public +%% License along with this software; see the file COPYING. +%% If not, see . + +%% -*- texinfo -*- +%% @documentencoding UTF-8 +%% @deftypefun {[@var{fd}, @var{filename}] =} make_temp_file__ (@var{tmpdir}, @var{prefix}) +%% Try to create temporary file in temporary directory @var{tmpdir} with prefix +%% @var{prefix} in the most secure and portable way possible. +%% +%% This function is not really intended for end users. +%% +%% @end deftypefun + + +%% This function is used in private/python_ipc_*.m +%% Assume Python IPC is not initialized yet + +function [fd, filename] = make_temp_file__ (tmpdir, prefix) + if (exist ('OCTAVE_VERSION', 'builtin')) + template = [tmpdir '/' prefix 'XXXXXX']; + [fd, filename, msg] = mkstemp (template); + if (fd == -1 || isequal (filename, '')) + error ('make_temp_file__: cannot create temp file: %s', msg); + end + + elseif (usejava ('jvm')) % java is required when not running octave + attrs = javaArray ('java.nio.file.attribute.FileAttribute', 0); + path = javaMethod ('createTempFile', 'java.nio.file.Files', + prefix, '', + attrs); + filename = javaMethod ('toString', path); + fd = fopen (filename, 'r+'); + + else + error ('make_temp_file__: cannot create temp file: please enable java'); + end +end + + +%!test +%! % general test +%! [fd, filename] = make_temp_file__ (tempdir (), 'octsympy-'); +%! assert (~isempty (strfind (filename, tempdir ()))); +%! assert (~isempty (strfind (filename, 'octsympy-'))); +%! assert (mod (fd, 1) == 0 && fd > 2); +%! s = 'hello, world'; +%! fprintf (fd, s); +%! assert (fclose (fd) == 0); +%! fd2 = fopen (filename); +%! s2 = fgets (fd2); +%! assert (isequal (s, s2)); +%! assert (fgets (fd2) == -1); +%! assert (fclose (fd2) == 0); +%! if (exist ('OCTAVE_VERSION', 'builtin')) +%! assert (unlink (filename) == 0); +%! else +%! delete (filename); +%! end + +%!error +%! if (exist ('OCTAVE_VERSION', 'builtin')) +%! make_temp_file__ ('/nonexistent', ''); +%! end diff --git a/inst/private/python_ipc_system.m b/inst/private/python_ipc_system.m index 1d2d03c6a..556d5c5ad 100644 --- a/inst/private/python_ipc_system.m +++ b/inst/private/python_ipc_system.m @@ -1,4 +1,5 @@ %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald +%% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% @@ -108,12 +109,13 @@ %% Generate a temp .py file then execute it with system() % can be useful for debugging, or if "python -c" fails for you if (isempty (tmpfilename)) - tmpfilename = [tempname() '_octsympytmp.py']; + [fd, tmpfilename] = make_temp_file__ (tempdir (), 'octsympy-tmpfile-'); if (verbose) disp (['This session will use the temp file "' tmpfilename '"']) end + else + fd = fopen (tmpfilename, 'w'); end - fd = fopen (tmpfilename, 'w'); fprintf(fd, '# temporary autogenerated code\n\n'); % we just added two more lines at the top info.prelines = info.prelines + 2; From be364a7d9f57cbef638e4039f614814190dd3ac1 Mon Sep 17 00:00:00 2001 From: Alex Vong Date: Fri, 24 Jun 2022 17:23:38 +0000 Subject: [PATCH 2/2] make_temp_dir__: New function. Try to create temporary directory in the most secure and portable way possible. Partially fixes #1145. * inst/make_temp_dir__.m: New function. * inst/@sym/function_handle.m: Use it. --- inst/@sym/function_handle.m | 19 +++++++------- inst/make_temp_dir__.m | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 inst/make_temp_dir__.m diff --git a/inst/@sym/function_handle.m b/inst/@sym/function_handle.m index e130e7e4a..61d63a787 100644 --- a/inst/@sym/function_handle.m +++ b/inst/@sym/function_handle.m @@ -1,4 +1,5 @@ %% Copyright (C) 2014-2019 Colin B. Macdonald +%% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% @@ -255,13 +256,13 @@ %!test %! % output to disk %! fprintf('\n') +%! temp_path = make_temp_dir__ (tempdir (), 'octsympy-temp-dir-'); %! if (exist ('OCTAVE_VERSION', 'builtin')) -%! temp_file = tempname('', 'oct_'); +%! temp_file = [temp_path '/oct_temp_file']; %! else -%! temp_file = tempname(); +%! temp_file = [temp_path '/temp_file']; %! end %! % allow loading function from temp_file -%! [temp_path, ans, ans] = fileparts(temp_file); %! addpath(temp_path); %! f = function_handle(2*x*y, 2^x, 'vars', {x y z}, 'file', temp_file); %! assert( isa(f, 'function_handle')) @@ -280,13 +281,13 @@ %!test %! % output to disk: also works with .m specified +%! temp_path = make_temp_dir__ (tempdir (), 'octsympy-temp-dir-'); %! if (exist ('OCTAVE_VERSION', 'builtin')) -%! temp_file = [tempname('', 'oct_') '.m']; +%! temp_file = [temp_path '/oct_temp_file.m']; %! else -%! temp_file = [tempname() '.m']; +%! temp_file = [temp_path '/temp_file.m']; %! end %! % allow loading function from temp_file -%! [temp_path, ans, ans] = fileparts(temp_file); %! addpath(temp_path); %! f = function_handle(2*x*y, 2^x, 'vars', {x y z}, 'file', temp_file); %! assert( isa(f, 'function_handle')) @@ -319,13 +320,13 @@ %! H = [x y z]; %! M = [x y; z 16]; %! V = [x;y;z]; +%! temp_path = make_temp_dir__ (tempdir (), 'octsympy-temp-dir-'); %! if (exist ('OCTAVE_VERSION', 'builtin')) -%! temp_file = tempname('', 'oct_'); +%! temp_file = [temp_path '/oct_temp_file']; %! else -%! temp_file = tempname(); +%! temp_file = [temp_path '/temp_file']; %! end %! % allow loading function from temp_file -%! [temp_path, ans, ans] = fileparts(temp_file); %! addpath(temp_path); %! h = function_handle(H, M, V, 'vars', {x y z}, 'file', temp_file); %! assert( isa(h, 'function_handle')) diff --git a/inst/make_temp_dir__.m b/inst/make_temp_dir__.m new file mode 100644 index 000000000..0eab4cdad --- /dev/null +++ b/inst/make_temp_dir__.m @@ -0,0 +1,50 @@ +%% Copyright (C) 2022 Alex Vong +%% +%% This file is part of OctSymPy. +%% +%% OctSymPy is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published +%% by the Free Software Foundation; either version 3 of the License, +%% or (at your option) any later version. +%% +%% This software is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty +%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +%% the GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public +%% License along with this software; see the file COPYING. +%% If not, see . + +%% -*- texinfo -*- +%% @documentencoding UTF-8 +%% @deftypefun {@var{path} =} make_temp_dir__ (@var{tmpdir}, @var{prefix}) +%% Try to create temporary directory in temporary directory @var{tmpdir} with +%% prefix @var{prefix} in the most secure and portable way possible. +%% +%% This function is not really intended for end users. +%% +%% @end deftypefun + + +function path = make_temp_dir__ (tmpdir, prefix) + cmd = {'import tempfile' + '(tmpdir, prefix) = _ins' + 'return tempfile.mkdtemp(dir=tmpdir, prefix=prefix)'}; + path = pycall_sympy__ (cmd, tmpdir, prefix); +end + + +%!test +%! % general test +%! path = make_temp_dir__ (tempdir (), 'octsympy-'); +%! assert (~isempty (strfind (path, tempdir ()))); +%! assert (~isempty (strfind (path, 'octsympy-'))); +%! assert (isfolder (path)); +%! assert (isequal (ls (path), '')); +%! assert (rmdir (path)); + +%!error +%! if (exist ('OCTAVE_VERSION', 'builtin')) +%! make_temp_dir__ ('/nonexistent', ''); +%! end