Blob Blame History Raw
From: Chris Liddell <chris.liddell@artifex.com>
Date: Sat, 1 Sep 2018 16:50:05 +0000 (+0100)
Subject: Bug 699658(related): Move recording of temp file names into C

Bug 699658(related): Move recording of temp file names into C

When we successfully create a temporary file from Postscript, either doing so
when SAFER is not in force, or when SAFER is in force, and creating it in
a write permitted directory, we record the file name so we can later delete
the file, even is SAFER has been engaged, or if the PermitWriting list has
changed to no longer the directory in question.

Previously the recording of the name was done in Postscript, even though the
checking was done in C.

This moves the recording of the names to C, meaning we can remove the Postscript
redefinitions of .tempfile and deletfile, and make the dictionary in question
noaccess.

Also, tidy up the adding of the temporary file directory to the list of
permitted directories, and include the list in all of the categories
(PermitFileWriting, PermitFileReading and PermitFileControl) - it was only
previously adding to writing.

https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=0704d18b10314d701a522ad6c16718e0b8e199b7
---

diff -up ghostscript-9.07/psi/int.mak.bz1661210 ghostscript-9.07/psi/int.mak
--- ghostscript-9.07/psi/int.mak.bz1661210	2018-12-20 17:38:21.683312408 +0100
+++ ghostscript-9.07/psi/int.mak	2018-12-20 17:38:40.583083097 +0100
@@ -330,7 +330,7 @@ $(PSOBJ)zfile.$(OBJ) : $(PSSRC)zfile.c $
  $(memory__h) $(string__h) $(unistd__h) $(stat__h) $(gp_h) $(gpmisc_h)\
  $(gscdefs_h) $(gsfname_h) $(gsstruct_h) $(gsutil_h) $(gxalloc_h) $(gxiodev_h)\
  $(dstack_h) $(estack_h) $(files_h)\
- $(ialloc_h) $(idict_h) $(ilevel_h) $(iname_h) $(iutil_h)\
+ $(ialloc_h) $(idict_h) $(iddict_h) $(ilevel_h) $(iname_h) $(iutil_h)\
  $(isave_h) $(main_h) $(sfilter_h) $(stream_h) $(strimpl_h) $(store_h)\
  $(zfile_h)
 	$(PSCC) $(PSO_)zfile.$(OBJ) $(C_) $(PSSRC)zfile.c
diff -up ghostscript-9.07/psi/zfile.c.bz1661210 ghostscript-9.07/psi/zfile.c
--- ghostscript-9.07/psi/zfile.c.bz1661210	2018-12-20 17:39:09.975726450 +0100
+++ ghostscript-9.07/psi/zfile.c	2018-12-20 17:44:50.698592208 +0100
@@ -35,6 +35,7 @@
 #include "iname.h"
 #include "isave.h"              /* for restore */
 #include "idict.h"
+#include "iddict.h"
 #include "iutil.h"
 #include "stream.h"
 #include "strimpl.h"
@@ -290,6 +291,28 @@ file_is_tempfile(i_ctx_t *i_ctx_p, const
     return true;
 }
 
+static int
+record_file_is_tempfile(i_ctx_t *i_ctx_p, const uchar *fname, int len, bool add)
+{
+    ref *SAFETY;
+    ref *tempfiles;
+    ref kname, bref;
+    int code = 0;
+
+    if (dict_find_string(systemdict, "SAFETY", &SAFETY) <= 0 ||
+            dict_find_string(SAFETY, "tempfiles", &tempfiles) <= 0) {
+        return 0;
+    }
+    if ((code = name_ref(imemory, fname, len, &kname, 1)) < 0) {
+        return code;
+    }
+    make_bool(&bref, true);
+    if (add)
+        return idict_put(tempfiles, &kname, &bref);
+    else
+        return idict_undef(tempfiles, &kname);
+}
+
 /* ------ Level 2 extensions ------ */
 
 /* <string> deletefile - */
@@ -299,17 +322,22 @@ zdeletefile(i_ctx_t *i_ctx_p)
     os_ptr op = osp;
     gs_parsed_file_name_t pname;
     int code = parse_real_file_name(op, &pname, imemory, "deletefile");
+    bool is_temp = false;
 
     if (code < 0)
         return code;
     if (pname.iodev == iodev_default(imemory)) {
         if ((code = check_file_permissions(i_ctx_p, pname.fname, pname.len,
                 pname.iodev, "PermitFileControl")) < 0 &&
-                 !file_is_tempfile(i_ctx_p, op->value.bytes, r_size(op))) {
+                 !(is_temp = file_is_tempfile(i_ctx_p, op->value.bytes, r_size(op)))) {
             return code;
         }
     }
     code = (*pname.iodev->procs.delete_file)(pname.iodev, pname.fname);
+
+    if (code >= 0 && is_temp)
+        code = record_file_is_tempfile(i_ctx_p, (unsigned char *)pname.fname, strlen(pname.fname), false);
+
     gs_free_file_name(&pname, "deletefile");
     if (code < 0)
         return code;
@@ -757,6 +785,7 @@ ztempfile(i_ctx_t *i_ctx_p)
     }
     make_string(op - 1, a_readonly | icurrent_space, fnlen, sbody);
     make_stream_file(op, s, fmode);
+    code = record_file_is_tempfile(i_ctx_p, (unsigned char *)fname, fnlen, true);
     return code;
 }
 
diff -up ghostscript-9.07/Resource/Init/gs_init.ps.bz1661210 ghostscript-9.07/Resource/Init/gs_init.ps
--- ghostscript-9.07/Resource/Init/gs_init.ps.bz1661210	2018-12-20 17:33:51.469591104 +0100
+++ ghostscript-9.07/Resource/Init/gs_init.ps	2018-12-20 17:35:36.694314341 +0100
@@ -2030,15 +2030,30 @@ systemdict /EPSBoundingBoxInit known { E
 .currentglobal //true .setglobal
 /SAFETY 2 dict
   dup /safe //false put
-  dup /tempfiles 10 dict readonly put
+  dup /tempfiles 10 dict noaccess put
 readonly def
 .setglobal
 
+/tempfilepaths
+[
+  (TMPDIR) getenv not
+  {
+    (TEMP) getenv not
+    {
+      (TMP) getenv not
+      {
+        (/temp) (/tmp)
+      } if
+    } if
+  } if
+] def
+
 /.locksafe {
   SAFETY /safe get not {
     <<
       /PermitFileReading [
         currentuserparams /PermitFileReading get aload pop
+        //tempfilepaths aload pop
         /FONTPATH .systemvar (*) .generate_dir_list_templates
           % Library files :
         /LIBPATH  .systemvar (*) .generate_dir_list_templates
@@ -2056,16 +2071,11 @@ readonly def
       ]
       /PermitFileWriting [
           currentuserparams /PermitFileWriting get aload pop
-          (TMPDIR) getenv not
-          {
-            (TEMP) getenv not
-            {
-              (TMP) getenv not
-              {
-                (/temp) (/tmp)
-              } if
-            } if
-          } if
+          //tempfilepaths aload pop
+      ]
+      /PermitFileControl [
+          currentuserparams /PermitFileControl get aload pop
+          //tempfilepaths aload pop
       ]
       /LockFilePermissions //true
     >> setuserparams
@@ -2082,6 +2092,8 @@ readonly def
   //SAFETY /safe //true .forceput % overrides readonly
 } .bind executeonly odef
 
+currentdict /tempfilepaths undef
+
 /.setsafe
 {
   SAFETY /safe get not {
@@ -2095,30 +2107,6 @@ readonly def
   .locksafe
 } .bind executeonly odef
 
-/deletefile {
-  dup { deletefile } stopped {
-    pop //deletefile $error /errorname get signalerror
-  } {
-    % deletefile succeeded. Remove from tempfile list if present
-    //SAFETY /tempfiles get exch cvn 2 copy known {
-      .forceundef
-    } {
-      pop pop
-    }
-    ifelse
-  }
-  ifelse
-} .bind executeonly odef
-
-% If a file is opened with .tempfile with SAFER not (yet) set,
-% the file can be deleted later, even if SAFER is set.
-/.tempfile {
-  .tempfile	% filename file
-    //SAFETY /safe get not { % only add the filename if we're not yet safe
-    //SAFETY /tempfiles get 2 .argindex //true .forceput
-  } if
-} .bind executeonly odef
-
 % If we are running in SAFER mode, lock things down
 SAFER { .setsafe } if