diff options
author | Robin Watts <robin.watts@artifex.com> | 2018-09-05 18:07:40 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2018-09-05 19:20:15 +0100 |
commit | 2b533271d8bd915593a2f8e1a1f446ee940c7d76 (patch) | |
tree | b15eb5abb50cdf3072fae00c098dab0b70b3b2fd | |
parent | a8c7899267121cb92503fe0f7e7f6ae433c386b1 (diff) | |
download | ghostpdl-2b533271d8bd915593a2f8e1a1f446ee940c7d76.tar.gz |
Fix arg_copy leaks.
When handling -d or -s args, the code currently arg_copies the string
it gets back, then uses that copied block to make postscript names
from.
Here we change the code so that postscript names are made in a
slightly different way, so they copy the string content. This means
we can free the arg_copied block afterwards, solving the leaks.
While we are here, remove a layer of nasty variable hiding macros
that do nothing but confuse things.
-rw-r--r-- | psi/iddict.h | 2 | ||||
-rw-r--r-- | psi/idict.c | 17 | ||||
-rw-r--r-- | psi/idict.h | 6 | ||||
-rw-r--r-- | psi/iinit.c | 42 | ||||
-rw-r--r-- | psi/imain.c | 6 | ||||
-rw-r--r-- | psi/imainarg.c | 34 | ||||
-rw-r--r-- | psi/interp.h | 4 |
7 files changed, 77 insertions, 34 deletions
diff --git a/psi/iddict.h b/psi/iddict.h index 67e6b887c..53d864b54 100644 --- a/psi/iddict.h +++ b/psi/iddict.h @@ -29,6 +29,8 @@ dict_put(pdref, key, pvalue, &idict_stack) #define idict_put_string(pdref, kstr, pvalue)\ dict_put_string(pdref, kstr, pvalue, &idict_stack) +#define idict_put_string_copy(pdref, kstr, pvalue)\ + dict_put_string_copy(pdref, kstr, pvalue, &idict_stack) #define idict_undef(pdref, key)\ dict_undef(pdref, key, &idict_stack) #define idict_copy(dfrom, dto)\ diff --git a/psi/idict.c b/psi/idict.c index 978f73d92..01d783712 100644 --- a/psi/idict.c +++ b/psi/idict.c @@ -555,6 +555,23 @@ dict_put_string(ref * pdref, const char *kstr, const ref * pvalue, return dict_put(pdref, &kname, pvalue, pds); } +/* + * Enter a key-value pair where the key is a C string that must be copied. + */ +int +dict_put_string_copy(ref * pdref, const char *kstr, const ref * pvalue, + dict_stack_t *pds) +{ + int code; + ref kname; + dict *pdict = pdref->value.pdict; + + if ((code = name_ref(dict_mem(pdict), + (const byte *)kstr, strlen(kstr), &kname, 1)) < 0) + return code; + return dict_put(pdref, &kname, pvalue, pds); +} + /* Remove an element from a dictionary. */ int dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds) diff --git a/psi/idict.h b/psi/idict.h index 31d33872b..c18d4f15e 100644 --- a/psi/idict.h +++ b/psi/idict.h @@ -125,6 +125,12 @@ int dict_put_string(ref * pdref, const char *kstr, const ref * pvalue, dict_stack_t *pds); /* + * Enter a key-value pair where the key is a (transient) C string. + */ +int dict_put_string_copy(ref * pdref, const char *kstr, const ref * pvalue, + dict_stack_t *pds); + +/* * Remove a key-value pair from a dictionary. * Return any of the same values as dict_put, except for 0 and gs_error_dictfull * which are converted to gs_error_undefined. diff --git a/psi/iinit.c b/psi/iinit.c index 3c4ccdced..1e2c46da8 100644 --- a/psi/iinit.c +++ b/psi/iinit.c @@ -105,6 +105,24 @@ i_initial_enter_name(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref) return i_initial_enter_name_in(i_ctx_p, systemdict, nstr, pref); } +/* Enter a name and value into a dictionary. */ +static int +i_initial_enter_name_copy_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr, + const ref * pref) +{ + int code = idict_put_string_copy(pdict, nstr, pref); + + if (code < 0) + lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n", + code, nstr, dict_length(pdict), dict_maxlength(pdict)); + return code; +} +int +i_initial_enter_name_copy(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref) +{ + return i_initial_enter_name_copy_in(i_ctx_p, systemdict, nstr, pref); +} + /* Remove a name from systemdict. */ void i_initial_remove_name(i_ctx_t *i_ctx_p, const char *nstr) @@ -297,7 +315,7 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem) } /* Enter names of referenced initial dictionaries into systemdict. */ - initial_enter_name("systemdict", systemdict); + i_initial_enter_name(i_ctx_p, "systemdict", systemdict); for (i = 0; i < icount; i++) { ref *idict = &idicts[i]; @@ -314,8 +332,8 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem) uint save_space = r_space(systemdict); r_set_space(systemdict, avm_local); - code = initial_enter_name(initial_dictionaries[i].name, - idict); + code = i_initial_enter_name(i_ctx_p, initial_dictionaries[i].name, + idict); r_set_space(systemdict, save_space); if (code < 0) return code; @@ -336,9 +354,9 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem) make_null(&vnull); make_true(&vtrue); make_false(&vfalse); - if ((code = initial_enter_name("null", &vnull)) < 0 || - (code = initial_enter_name("true", &vtrue)) < 0 || - (code = initial_enter_name("false", &vfalse)) < 0 + if ((code = i_initial_enter_name(i_ctx_p, "null", &vnull)) < 0 || + (code = i_initial_enter_name(i_ctx_p, "true", &vtrue)) < 0 || + (code = i_initial_enter_name(i_ctx_p, "false", &vfalse)) < 0 ) return code; } @@ -356,7 +374,7 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem) if ((code = name_enter_string(imemory, (const char *)gs_error_names[i], era.value.refs + i)) < 0) return code; - return initial_enter_name("ErrorNames", &era); + return i_initial_enter_name(i_ctx_p, "ErrorNames", &era); } } @@ -398,11 +416,11 @@ zop_init(i_ctx_t *i_ctx_p) (const byte *)gs_productfamily); make_int(&vre, gs_revision); make_int(&vrd, gs_revisiondate); - if ((code = initial_enter_name("copyright", &vcr)) < 0 || - (code = initial_enter_name("product", &vpr)) < 0 || - (code = initial_enter_name("productfamily", &vpf)) < 0 || - (code = initial_enter_name("revision", &vre)) < 0 || - (code = initial_enter_name("revisiondate", &vrd)) < 0) + if ((code = i_initial_enter_name(i_ctx_p, "copyright", &vcr)) < 0 || + (code = i_initial_enter_name(i_ctx_p, "product", &vpr)) < 0 || + (code = i_initial_enter_name(i_ctx_p, "productfamily", &vpf)) < 0 || + (code = i_initial_enter_name(i_ctx_p, "revision", &vre)) < 0 || + (code = i_initial_enter_name(i_ctx_p, "revisiondate", &vrd)) < 0) return code; } diff --git a/psi/imain.c b/psi/imain.c index 138bfc82b..9fc72bb10 100644 --- a/psi/imain.c +++ b/psi/imain.c @@ -264,18 +264,18 @@ int gs_main_init2aux(gs_main_instance * minst) { /* Set up the array of additional initialization files. */ make_const_string(&ifa, a_readonly | avm_foreign, gs_init_files_sizeof - 2, gs_init_files); - code = initial_enter_name("INITFILES", &ifa); + code = i_initial_enter_name(i_ctx_p, "INITFILES", &ifa); if (code < 0) return code; /* Set up the array of emulator names. */ make_const_string(&ifa, a_readonly | avm_foreign, gs_emulators_sizeof - 2, gs_emulators); - code = initial_enter_name("EMULATORS", &ifa); + code = i_initial_enter_name(i_ctx_p, "EMULATORS", &ifa); if (code < 0) return code; /* Pass the search path. */ - code = initial_enter_name("LIBPATH", &minst->lib_path.list); + code = i_initial_enter_name(i_ctx_p, "LIBPATH", &minst->lib_path.list); if (code < 0) return code; diff --git a/psi/imainarg.c b/psi/imainarg.c index fb16f4b07..9cd62c821 100644 --- a/psi/imainarg.c +++ b/psi/imainarg.c @@ -312,9 +312,6 @@ swproc(gs_main_instance * minst, const char *arg, arg_list * pal) char sw = arg[1]; ref vtrue; int code = 0; -#undef initial_enter_name -#define initial_enter_name(nstr, pvalue)\ - i_initial_enter_name(minst->i_ctx_p, nstr, pvalue) make_true(&vtrue); arg += 2; /* skip - and letter */ @@ -603,10 +600,10 @@ run_stdin: return gs_error_Fatal; } make_int(&value, width); - initial_enter_name("DEVICEWIDTH", &value); + i_initial_enter_name(minst->i_ctx_p, "DEVICEWIDTH", &value); make_int(&value, height); - initial_enter_name("DEVICEHEIGHT", &value); - initial_enter_name("FIXEDMEDIA", &vtrue); + i_initial_enter_name(minst->i_ctx_p, "DEVICEHEIGHT", &value); + i_initial_enter_name(minst->i_ctx_p, "FIXEDMEDIA", &vtrue); break; } case 'h': /* print help */ @@ -705,9 +702,9 @@ run_stdin: memcpy(str, adef, len); make_const_string(&value, a_readonly | avm_system, len, str); ialloc_set_space(idmemory, space); - initial_enter_name("OutputFile", &value); - initial_enter_name("NOPAUSE", &vtrue); - initial_enter_name("BATCH", &vtrue); + i_initial_enter_name(minst->i_ctx_p, "OutputFile", &value); + i_initial_enter_name(minst->i_ctx_p, "NOPAUSE", &vtrue); + i_initial_enter_name(minst->i_ctx_p, "BATCH", &vtrue); } break; case 'P': /* choose whether search '.' first */ @@ -723,7 +720,7 @@ run_stdin: case 'q': /* quiet startup */ if ((code = gs_main_init1(minst)) < 0) return code; - initial_enter_name("QUIET", &vtrue); + i_initial_enter_name(minst->i_ctx_p, "QUIET", &vtrue); break; case 'r': /* define device resolution */ { @@ -741,10 +738,10 @@ run_stdin: /* fall through */ case 2: /* -r<xres>x<yres> */ make_real(&value, xres); - initial_enter_name("DEVICEXRESOLUTION", &value); + i_initial_enter_name(minst->i_ctx_p, "DEVICEXRESOLUTION", &value); make_real(&value, yres); - initial_enter_name("DEVICEYRESOLUTION", &value); - initial_enter_name("FIXEDRESOLUTION", &vtrue); + i_initial_enter_name(minst->i_ctx_p, "DEVICEYRESOLUTION", &value); + i_initial_enter_name(minst->i_ctx_p, "FIXEDRESOLUTION", &vtrue); } break; } @@ -772,6 +769,7 @@ run_stdin: } if (eqp == adef) { puts(minst->heap, "Usage: -dNAME, -dNAME=TOKEN, -sNAME=STRING"); + arg_free((char *)adef, minst->heap); return gs_error_Fatal; } if (eqp == NULL) { @@ -828,6 +826,7 @@ run_stdin: code = gs_scan_token(minst->i_ctx_p, &value, &state); if (code) { outprintf(minst->heap, "Invalid value for option -d%s, -dNAME= must be followed by a valid token\n", arg); + arg_free((char *)adef, minst->heap); return gs_error_Fatal; } if (r_has_type_attrs(&value, t_name, @@ -847,6 +846,7 @@ run_stdin: make_false(&value); else { outprintf(minst->heap, "Invalid value for option -d%s, use -sNAME= to define string constants\n", arg); + arg_free((char *)adef, minst->heap); return gs_error_Fatal; } } @@ -857,17 +857,21 @@ run_stdin: if (body == NULL) { lprintf("Out of memory!\n"); + arg_free((char *)adef, minst->heap); return gs_error_Fatal; } memcpy(body, eqp, len); make_const_string(&value, a_readonly | avm_system, len, body); - if ((code = try_stdout_redirect(minst, adef, eqp)) < 0) + if ((code = try_stdout_redirect(minst, adef, eqp)) < 0) { + arg_free((char *)adef, minst->heap); return code; + } } ialloc_set_space(idmemory, space); } /* Enter the name in systemdict. */ - initial_enter_name(adef, &value); + i_initial_enter_name_copy(minst->i_ctx_p, adef, &value); + arg_free((char *)adef, minst->heap); break; } case 'u': /* undefine name */ diff --git a/psi/interp.h b/psi/interp.h index 10c037a75..5e5ca583e 100644 --- a/psi/interp.h +++ b/psi/interp.h @@ -23,13 +23,9 @@ /* Enter a name and value into systemdict. */ int i_initial_enter_name(i_ctx_t *, const char *, const ref *); -#define initial_enter_name(nstr, pvalue)\ - i_initial_enter_name(i_ctx_p, nstr, pvalue) /* Remove a name from systemdict. */ void i_initial_remove_name(i_ctx_t *, const char *); -#define initial_remove_name(nstr)\ - i_initial_remove_name(i_ctx_p, nstr) /* ------ interp.c ------ */ |