summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/ghostscript/files/0003-Bug-699832-add-control-over-hiding-error-handlers.patch
blob: cd786595833e99541e2a0de159f8c21a7d096206 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
From 1f9a91c86bd56acf57826b9b0e020ebe1953e2ae Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 4 Oct 2018 10:42:13 +0100
Subject: [PATCH 3/5] Bug 699832: add control over hiding error handlers.

With a previous commit changing error handling in SAFER so the handler gets
passed a name object (rather than executable object), it is less critical to
hide the error handlers.

This introduces a -dSAFERERRORS option to force only use of the default error
handlers.

It also adds a .setsafererrors Postscript call, meaning a caller, without
-dSAFERERRORS, can create their own default error handlers (in errordict, as
normal), and then call .setsafererrors meaning their own handlers are always
called.

With -dSAFERERRORS or after a call to .setsafererrors, .setsafererrors is
removed.

CVE: CVE-2018-17961
Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git]
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
---
 Resource/Init/gs_init.ps | 42 +++++++++++++++++++++++++++++------------
 psi/interp.c             | 49 ++++++++++++++++++++++++++++--------------------
 2 files changed, 59 insertions(+), 32 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index bec307d..f952f32 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -188,6 +188,16 @@ currentdict /DELAYSAFER known { /DELAYSAFER //true def /NOSAFER //true def } if
   currentdict /PARANOIDSAFER known or	% PARANOIDSAFER is equivalent
 }
 ifelse def
+
+/SAFERERRORS
+currentdict /NOSAFERERRORS known
+{
+  //false
+}
+{
+  currentdict /SAFERERRORS known
+} ifelse def
+
 currentdict /SHORTERRORS known   /SHORTERRORS exch def
 currentdict /TTYPAUSE known   /TTYPAUSE exch def
 currentdict /WRITESYSTEMDICT known   /WRITESYSTEMDICT exch def
@@ -1123,12 +1133,23 @@ errordict begin
  } bind def
 end		% errordict
 
-% Put all the default handlers in gserrordict
-gserrordict
-errordict {2 index 3 1 roll put} forall
-noaccess pop
-% remove the non-standard errors from errordict
+gserrordict /unknownerror errordict /unknownerror get put
 errordict /unknownerror .undef
+
+/.SAFERERRORLIST ErrorNames def
+/.setsafererrors
+{
+% Put all the requested handlers in gserrordict
+  gserrordict
+  //.SAFERERRORLIST
+  {dup errordict exch get 2 index 3 1 roll put} forall
+  noaccess pop
+  systemdict /.setsafeerrors .forceundef
+  systemdict /.SAFERERRORLIST .forceundef
+} bind executeonly odef
+
+SAFERERRORS {.setsafererrors} if
+
 % Define a stable private copy of handleerror that we will always use under
 % JOBSERVER mode.
 /.GShandleerror errordict /handleerror get def
@@ -1760,18 +1781,15 @@ currentdict /.runlibfile .undef
 
 % Bind all the operators defined as procedures.
 /.bindoperators		% binds operators in currentdict
- { % Temporarily disable the typecheck error.
-   errordict /typecheck 2 copy get
-   errordict /typecheck { pop } put	% pop the command
+ {
    currentdict
     { dup type /operatortype eq
-       { % This might be a real operator, so bind might cause a typecheck,
-         % but we've made the error a no-op temporarily.
-         .bind
+       {
+         % This might be a real operator, so bind might cause a typecheck
+         {.bind} .internalstopped pop
        }
       if pop pop
     } forall
-   put
  } def
 DELAYBIND not { .bindoperators } if
 
diff --git a/psi/interp.c b/psi/interp.c
index 3dd5f7a..cd894f9 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -662,27 +662,18 @@ again:
     if (gs_errorname(i_ctx_p, code, &error_name) < 0)
         return code;            /* out-of-range error code! */
 
-    /*  If LockFilePermissions is true, we only refer to gserrordict, which
-     *  is not accessible to Postcript jobs
+    /*  We refer to gserrordict first, which is not accessible to Postcript jobs
+     *  If we're running with SAFERERRORS all the handlers are copied to gserrordict
+     *  so we'll always find the default one. If not SAFERERRORS, only gs specific
+     *  errors are in gserrordict.
      */
-    if (i_ctx_p->LockFilePermissions) {
-        if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
-              dict_find(perrordict, &error_name, &epref) <= 0))
-            )
-            return code;            /* error name not in errordict??? */
-    }
-    else {
-        /*
-         * For greater Adobe compatibility, only the standard PostScript errors
-         * are defined in errordict; the rest are in gserrordict.
-         */
-        if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
-            (dict_find(perrordict, &error_name, &epref) <= 0 &&
-             (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
-              dict_find(perrordict, &error_name, &epref) <= 0))
-            )
-            return code;            /* error name not in errordict??? */
-    }
+    if (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
+        (dict_find(perrordict, &error_name, &epref) <= 0 &&
+         (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
+          dict_find(perrordict, &error_name, &epref) <= 0))
+        )
+        return code;            /* error name not in errordict??? */
+
     doref = *epref;
     epref = &doref;
     /* Push the error object on the operand stack if appropriate. */
@@ -695,6 +686,24 @@ again:
         }
         *osp = *perror_object;
         errorexec_find(i_ctx_p, osp);
+        /* If using SAFER, hand a name object to the error handler, rather than the executable
+         * object/operator itself.
+         */
+        if (i_ctx_p->LockFilePermissions) {
+            code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
+            if (code < 0) {
+                const char *unknownstr = "--unknown--";
+                rlen = strlen(unknownstr);
+                memcpy(buf, unknownstr, rlen);
+            }
+            else {
+                buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
+                rlen += 4;
+            }
+            code = name_ref(imemory, buf, rlen, osp, 1);
+            if (code < 0)
+                make_null(osp);
+        }
     }
     goto again;
 }
-- 
2.7.4