From 34a8c5aa987d4db5234172a62218b168371606b1 Mon Sep 17 00:00:00 2001 From: Chris Liddell Date: Tue, 2 Oct 2018 16:02:58 +0100 Subject: [PATCH 4/5] For hidden operators, pass a name object to error handler. In normal operation, Postscript error handlers are passed the object which triggered the error: this is invariably an operator object. The issue arises when an error is triggered by an operator which is for internal use only, and that operator is then passed to the error handler, meaning it becomes visible to the error handler code. By converting to a name object, the error message is still valid, but we no longer expose internal use only operators. The change in gs_dps1.ps is related to the above: previously an error in scheck would throw an error against .gcheck, but as .gcheck is now a hidden operator, it resulted in a name object being passed to the error handler. As scheck is a 'real' operator, it's better to use the real operator, rather than the name of an internal, hidden one. CVE: CVE-2018-17961 Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] Signed-off-by: Hongxu Jia --- Resource/Init/gs_dps1.ps | 2 +- psi/interp.c | 33 ++++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps index 1182f53..ec5db61 100644 --- a/Resource/Init/gs_dps1.ps +++ b/Resource/Init/gs_dps1.ps @@ -21,7 +21,7 @@ level2dict begin % ------ Virtual memory ------ % /currentshared /.currentglobal load def -/scheck /.gcheck load def +/scheck {.gcheck} bind odef %****** FOLLOWING IS WRONG ****** /shareddict currentdict /globaldict .knownget not { 20 dict } if def diff --git a/psi/interp.c b/psi/interp.c index cd894f9..b70769d 100644 --- a/psi/interp.c +++ b/psi/interp.c @@ -678,6 +678,8 @@ again: epref = &doref; /* Push the error object on the operand stack if appropriate. */ if (!GS_ERROR_IS_INTERRUPT(code)) { + byte buf[260], *bufptr; + uint rlen; /* Replace the error object if within an oparray or .errorexec. */ osp++; if (osp >= ostop) { @@ -686,23 +688,36 @@ 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) { + + if (!r_has_type(osp, t_string) && !r_has_type(osp, t_name)) { 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); + bufptr = buf; } else { - buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-'; - rlen += 4; + ref *tobj; + bufptr[rlen] = '\0'; + /* Only pass a name object if the operator doesn't exist in systemdict + * i.e. it's an internal operator we have hidden + */ + code = dict_find_string(systemdict, (const char *)bufptr, &tobj); + if (code < 0) { + buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-'; + rlen += 4; + bufptr = buf; + } + else { + bufptr = NULL; + } + } + if (bufptr) { + code = name_ref(imemory, buf, rlen, osp, 1); + if (code < 0) + make_null(osp); } - code = name_ref(imemory, buf, rlen, osp, 1); - if (code < 0) - make_null(osp); } } goto again; -- 2.7.4