From ebabebad34a3811230b7bfe351eface7f5efc8a9 Mon Sep 17 00:00:00 2001 From: Ken Sharp Date: Wed, 8 Apr 2020 16:06:44 +0100 Subject: [PATCH] PostScript interpreter - don't leave A85Decode pdf_rules uninitialised Bug #702319 "Read of uninitialized value according to valgrind..." There are a number of other bugs which relate to this particular problem: 690976, 692983 and 693485. The problem has come about as a cumulative result of working on these bugs. Starting with commit : http://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=e0ecca32ecd12dae3310fac4b65dc224031c85a2 for bug 690976 a new flag 'pdf_rules' was added to the Ascii85Decode state. This is initialised from the dictionary operand in PostScript by zA85D() in zfdecode.c. When this flag is true the ASCII85Decode filter will silently accept just '~' as a valid termination for a string (should be '~>'). However this is not the only way to initialise an Ascii85Decode filter, the PostScript token scanner can also use s_A85D_init_inline() which does not initialise the flag. From this point we have the potential for testing an unitialised variable in s_A85D_process(), if we get an encoded string which terminates with a '~' and the filter was instantiated from PostScript. When fixing bug 692983, this commit: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=d561224d1495321d40012230abbcf835b298f557 Alex specifically added a comment that pdf_rules must not be initialised in s_A85D_init_inline() but didn't say why! The reason is that the regular stream initialisation code (s_A85D-init) also uses this inline function, so if it altered pdf_rules it would overwrite the value previously set by zA85D(). Since the initialisation is done in two places, the only way to fix this is to initialise pdf_rules in gs_scan_token() which this commit duly does. I've also added comments in s_A85D_init_inline to explain more clearly *why* pdf_rules must not be initialised here. --- base/sa85d.h | 9 ++++++++- psi/iscan.c | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/base/sa85d.h b/base/sa85d.h index 6e74622..8685af7 100644 --- a/base/sa85d.h +++ b/base/sa85d.h @@ -41,7 +41,14 @@ typedef struct stream_A85D_state_s { (ss)->min_left = 1; \ (ss)->word = 0; \ (ss)->odd = 0; \ - /* pdf_rules should not be initialized here */ \ + /* pdf_rules should not be initialized here. This flag is initialised in\ + * zA85D to either true or false, and this inline function is called *after*\ + * that in s_A85D_init to do the remaining initialisation. However, this\ + * inline function is also called from gs_scan_token to handle inline\ + * ASCII85 strings. These are not to be interpreted using PDF rules\ + * and so we must not set the flag here, but in the relevant calling\ + * functions.\ + */ \ (ss)->require_eod=false; \ END extern const stream_template s_A85D_template; diff --git a/psi/iscan.c b/psi/iscan.c index e5956e1..9b7151a 100644 --- a/psi/iscan.c +++ b/psi/iscan.c @@ -581,6 +581,10 @@ gs_scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate) s_A85D_init_inline(&sstate.s_ss.a85d); sstate.s_ss.st.templat = &s_A85D_template; sstate.s_ss.a85d.require_eod = true; + /* If this is an inline ASCII string, interpret it normally, throw an error + * if it fails rather than ignoring it as PDF (Acrobat) does. + */ + sstate.s_ss.a85d.pdf_rules = false; goto str; } sputback_inline(s, sptr, endptr); -- 1.8.3.1