blob: cd786595833e99541e2a0de159f8c21a7d096206 [file] [log] [blame]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001From 1f9a91c86bd56acf57826b9b0e020ebe1953e2ae Mon Sep 17 00:00:00 2001
2From: Chris Liddell <chris.liddell@artifex.com>
3Date: Thu, 4 Oct 2018 10:42:13 +0100
4Subject: [PATCH 3/5] Bug 699832: add control over hiding error handlers.
5
6With a previous commit changing error handling in SAFER so the handler gets
7passed a name object (rather than executable object), it is less critical to
8hide the error handlers.
9
10This introduces a -dSAFERERRORS option to force only use of the default error
11handlers.
12
13It also adds a .setsafererrors Postscript call, meaning a caller, without
14-dSAFERERRORS, can create their own default error handlers (in errordict, as
15normal), and then call .setsafererrors meaning their own handlers are always
16called.
17
18With -dSAFERERRORS or after a call to .setsafererrors, .setsafererrors is
19removed.
20
21CVE: CVE-2018-17961
22Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git]
23Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
24---
25 Resource/Init/gs_init.ps | 42 +++++++++++++++++++++++++++++------------
26 psi/interp.c | 49 ++++++++++++++++++++++++++++--------------------
27 2 files changed, 59 insertions(+), 32 deletions(-)
28
29diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
30index bec307d..f952f32 100644
31--- a/Resource/Init/gs_init.ps
32+++ b/Resource/Init/gs_init.ps
33@@ -188,6 +188,16 @@ currentdict /DELAYSAFER known { /DELAYSAFER //true def /NOSAFER //true def } if
34 currentdict /PARANOIDSAFER known or % PARANOIDSAFER is equivalent
35 }
36 ifelse def
37+
38+/SAFERERRORS
39+currentdict /NOSAFERERRORS known
40+{
41+ //false
42+}
43+{
44+ currentdict /SAFERERRORS known
45+} ifelse def
46+
47 currentdict /SHORTERRORS known /SHORTERRORS exch def
48 currentdict /TTYPAUSE known /TTYPAUSE exch def
49 currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def
50@@ -1123,12 +1133,23 @@ errordict begin
51 } bind def
52 end % errordict
53
54-% Put all the default handlers in gserrordict
55-gserrordict
56-errordict {2 index 3 1 roll put} forall
57-noaccess pop
58-% remove the non-standard errors from errordict
59+gserrordict /unknownerror errordict /unknownerror get put
60 errordict /unknownerror .undef
61+
62+/.SAFERERRORLIST ErrorNames def
63+/.setsafererrors
64+{
65+% Put all the requested handlers in gserrordict
66+ gserrordict
67+ //.SAFERERRORLIST
68+ {dup errordict exch get 2 index 3 1 roll put} forall
69+ noaccess pop
70+ systemdict /.setsafeerrors .forceundef
71+ systemdict /.SAFERERRORLIST .forceundef
72+} bind executeonly odef
73+
74+SAFERERRORS {.setsafererrors} if
75+
76 % Define a stable private copy of handleerror that we will always use under
77 % JOBSERVER mode.
78 /.GShandleerror errordict /handleerror get def
79@@ -1760,18 +1781,15 @@ currentdict /.runlibfile .undef
80
81 % Bind all the operators defined as procedures.
82 /.bindoperators % binds operators in currentdict
83- { % Temporarily disable the typecheck error.
84- errordict /typecheck 2 copy get
85- errordict /typecheck { pop } put % pop the command
86+ {
87 currentdict
88 { dup type /operatortype eq
89- { % This might be a real operator, so bind might cause a typecheck,
90- % but we've made the error a no-op temporarily.
91- .bind
92+ {
93+ % This might be a real operator, so bind might cause a typecheck
94+ {.bind} .internalstopped pop
95 }
96 if pop pop
97 } forall
98- put
99 } def
100 DELAYBIND not { .bindoperators } if
101
102diff --git a/psi/interp.c b/psi/interp.c
103index 3dd5f7a..cd894f9 100644
104--- a/psi/interp.c
105+++ b/psi/interp.c
106@@ -662,27 +662,18 @@ again:
107 if (gs_errorname(i_ctx_p, code, &error_name) < 0)
108 return code; /* out-of-range error code! */
109
110- /* If LockFilePermissions is true, we only refer to gserrordict, which
111- * is not accessible to Postcript jobs
112+ /* We refer to gserrordict first, which is not accessible to Postcript jobs
113+ * If we're running with SAFERERRORS all the handlers are copied to gserrordict
114+ * so we'll always find the default one. If not SAFERERRORS, only gs specific
115+ * errors are in gserrordict.
116 */
117- if (i_ctx_p->LockFilePermissions) {
118- if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
119- dict_find(perrordict, &error_name, &epref) <= 0))
120- )
121- return code; /* error name not in errordict??? */
122- }
123- else {
124- /*
125- * For greater Adobe compatibility, only the standard PostScript errors
126- * are defined in errordict; the rest are in gserrordict.
127- */
128- if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
129- (dict_find(perrordict, &error_name, &epref) <= 0 &&
130- (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
131- dict_find(perrordict, &error_name, &epref) <= 0))
132- )
133- return code; /* error name not in errordict??? */
134- }
135+ if (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
136+ (dict_find(perrordict, &error_name, &epref) <= 0 &&
137+ (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
138+ dict_find(perrordict, &error_name, &epref) <= 0))
139+ )
140+ return code; /* error name not in errordict??? */
141+
142 doref = *epref;
143 epref = &doref;
144 /* Push the error object on the operand stack if appropriate. */
145@@ -695,6 +686,24 @@ again:
146 }
147 *osp = *perror_object;
148 errorexec_find(i_ctx_p, osp);
149+ /* If using SAFER, hand a name object to the error handler, rather than the executable
150+ * object/operator itself.
151+ */
152+ if (i_ctx_p->LockFilePermissions) {
153+ code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
154+ if (code < 0) {
155+ const char *unknownstr = "--unknown--";
156+ rlen = strlen(unknownstr);
157+ memcpy(buf, unknownstr, rlen);
158+ }
159+ else {
160+ buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
161+ rlen += 4;
162+ }
163+ code = name_ref(imemory, buf, rlen, osp, 1);
164+ if (code < 0)
165+ make_null(osp);
166+ }
167 }
168 goto again;
169 }
170--
1712.7.4
172