summaryrefslogtreecommitdiff
path: root/base/gslibctx.c
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2019-08-12 16:30:46 +0100
committerRobin Watts <Robin.Watts@artifex.com>2019-08-14 18:03:29 +0100
commit813d7e96c8733f85d59a62732171cf7cedfc087d (patch)
treed858eb3812f9c15c510205b169836a1b89bda493 /base/gslibctx.c
parent8ba95fb06387572160fee5e4c1e51d972401566e (diff)
downloadghostpdl-813d7e96c8733f85d59a62732171cf7cedfc087d.tar.gz
Capture args to feed to pdfwrite.
To facilitate debugging, we want a way to pickle the gs invocation used into device output (for devices that want it). We therefore amend the argument processing logic to pass arguments to gs_lib_ctx, where they will are 'sanitized' and stored in a list. This list can then be accessed by a device. We are careful to sanitize the args so as not to reveal paths or secret passwords/code etc. Essentially we never store any filenames or string values stored (except for certain whitelisted -s options). It is likely that we'll want to expand the whitelisted values in future.
Diffstat (limited to 'base/gslibctx.c')
-rw-r--r--base/gslibctx.c199
1 files changed, 198 insertions, 1 deletions
diff --git a/base/gslibctx.c b/base/gslibctx.c
index 923f8207d..6e57fe025 100644
--- a/base/gslibctx.c
+++ b/base/gslibctx.c
@@ -30,6 +30,7 @@
#ifdef WITH_CAL
#include "cal.h"
#endif
+#include "gsargs.h"
/* Include the extern for the device list. */
extern_gs_lib_device_list();
@@ -385,7 +386,7 @@ void gs_lib_ctx_fin(gs_memory_t *mem)
{
gs_lib_ctx_t *ctx;
gs_memory_t *ctx_mem;
- int refs;
+ int refs, i;
gs_fs_list_t *fs;
if (!mem || !mem->gs_lib_ctx)
@@ -433,6 +434,11 @@ void gs_lib_ctx_fin(gs_memory_t *mem)
gs_free_object(fs->memory, fs, "gs_lib_ctx_fin");
fs = next;
}
+
+ for (i = 0; i < ctx->core->argc; i++)
+ gs_free_object(ctx->core->memory, ctx->core->argv[i], "gs_lib_ctx_arg");
+ gs_free_object(ctx->core->memory, ctx->core->argv, "gs_lib_ctx_args");
+
gs_free_object(ctx->core->memory, ctx->core, "gs_lib_ctx_fin");
}
remove_ctx_pointers(ctx_mem);
@@ -855,3 +861,194 @@ gs_remove_fs(const gs_memory_t *mem,
pfs = &(*pfs)->next;
}
}
+
+int
+gs_lib_ctx_stash_sanitized_arg(gs_lib_ctx_t *ctx, const char *arg)
+{
+ gs_lib_ctx_core_t *core;
+ size_t len;
+ const char *p;
+ int elide = 0;
+
+ if (ctx == NULL || ctx->core == NULL || arg == NULL)
+ return 0;
+
+ /* Sanitize arg */
+ switch(*arg)
+ {
+ case '-':
+ switch (arg[1])
+ {
+ case 0: /* We can let - through unchanged */
+ case 'd': /* We can let -dFoo=<whatever> through unchanged */
+ case 'D': /* We can let -DFoo=<whatever> through unchanged */
+ case 'r': /* We can let -r through unchanged */
+ case 'Z': /* We can let -Z through unchanged */
+ case 'g': /* We can let -g through unchanged */
+ case 'P': /* We can let -P through unchanged */
+ case '-': /* We can let -- through unchanged */
+ case '+': /* We can let -+ through unchanged */
+ case '_': /* We can let -_ through unchanged */
+ case 'u': /* We can let -u through unchanged */
+ case 'q': /* We can let -q through unchanged */
+ break;
+ case 'I': /* Let through the I, but hide anything else */
+ case 'f': /* Let through the I, but hide anything else */
+ if (arg[2] == 0)
+ break;
+ p = arg+2;
+ while (p == 32)
+ p++;
+ elide = 1;
+ break;
+ case 's':
+ case 'S':
+ /* By default, we want to keep the key, but lose the value */
+ p = arg+2;
+ while (*p && *p != '=')
+ p++;
+ if (*p == '=')
+ p++;
+ if (*p == 0)
+ break; /* No value to elide */
+ /* Check for our whitelisted values here */
+ if (!memcmp("DEFAULTPAPERSIZE", arg+2, p-arg-3))
+ break;
+ if (!memcmp("DEVICE", arg+2, p-arg-3))
+ break;
+ if (!memcmp("PAPERSIZE", arg+2, p-arg-3))
+ break;
+ if (!memcmp("SUBSTFONT", arg+2, p-arg-3))
+ break;
+ if (!memcmp("ColorConversionStrategy", arg+2, p-arg-3))
+ break;
+ if (!memcmp("PageList", arg+2, p-arg-3))
+ break;
+ if (!memcmp("ProcessColorModel", arg+2, p-arg-3))
+ break;
+ /* Didn't match a whitelisted value, so elide it. */
+ elide = 1;
+ break;
+ default:
+ /* Shouldn't happen, but elide it just in case */
+ arg = "?";
+ break;
+ }
+ break;
+ case '@':
+ /* Shouldn't happen */
+ default:
+ /* Anything else should be elided */
+ arg = "?";
+ break;
+ }
+
+ core = ctx->core;
+ if (elide)
+ len = p-arg;
+ else
+ len = strlen(arg);
+
+ if (core->arg_max == core->argc) {
+ char **argv;
+ int newlen = core->arg_max * 2;
+ if (newlen == 0)
+ newlen = 4;
+ argv = (char **)gs_alloc_bytes(ctx->core->memory, sizeof(char *) * newlen,
+ "gs_lib_ctx_args");
+ if (argv == NULL)
+ return gs_error_VMerror;
+ if (core->argc > 0) {
+ memcpy(argv, core->argv, sizeof(char *) * core->argc);
+ gs_free_object(ctx->memory, core->argv, "gs_lib_ctx_args");
+ }
+ core->argv = argv;
+ core->arg_max = newlen;
+ }
+
+ core->argv[core->argc] = (char *)gs_alloc_bytes(ctx->core->memory, len+1+elide,
+ "gs_lib_ctx_arg");
+ if (core->argv[core->argc] == NULL)
+ return gs_error_VMerror;
+ memcpy(core->argv[core->argc], arg, len);
+ if (elide) {
+ core->argv[core->argc][len] = '?';
+ }
+ core->argv[core->argc][len+elide] = 0;
+ core->argc++;
+
+ return 0;
+}
+
+int
+gs_lib_ctx_stash_exe(gs_lib_ctx_t *ctx, const char *arg)
+{
+ gs_lib_ctx_core_t *core;
+ size_t len;
+ const char *p, *word;
+ const char *sep = gp_file_name_directory_separator();
+ size_t seplen = strlen(sep);
+
+ if (ctx == NULL || ctx->core == NULL || arg == NULL)
+ return 0;
+
+ /* Sanitize arg */
+ p = arg;
+ word = NULL;
+ for (p = arg; *p; p++) {
+ if (memcmp(sep, p, seplen) == 0) {
+ word = p+seplen;
+ p += seplen-1;
+ }
+#if defined(__WIN32__) || defined(__OS2__) || defined(METRO)
+ if (*p == '\\')
+ word = p+1;
+#endif
+ }
+ len = p - (word ? word : arg) + 1;
+ if (word)
+ len += 5;
+
+ core = ctx->core;
+ if (core->arg_max == core->argc) {
+ char **argv;
+ int newlen = core->arg_max * 2;
+ if (newlen == 0)
+ newlen = 4;
+ argv = (char **)gs_alloc_bytes(ctx->core->memory, sizeof(char *) * newlen,
+ "gs_lib_ctx_args");
+ if (argv == NULL)
+ return gs_error_VMerror;
+ if (core->argc > 0) {
+ memcpy(argv, core->argv, sizeof(char *) * core->argc);
+ gs_free_object(ctx->memory, core->argv, "gs_lib_ctx_args");
+ }
+ core->argv = argv;
+ core->arg_max = newlen;
+ }
+
+ core->argv[core->argc] = (char *)gs_alloc_bytes(ctx->core->memory, len,
+ "gs_lib_ctx_arg");
+ if (core->argv[core->argc] == NULL)
+ return gs_error_VMerror;
+ if (word)
+ strcpy(core->argv[core->argc], "path/");
+ else
+ core->argv[core->argc][0] = 0;
+ strcat(core->argv[core->argc], word ? word : arg);
+ core->argc++;
+
+ return 0;
+}
+
+int gs_lib_ctx_get_args(gs_lib_ctx_t *ctx, const char ***argv)
+{
+ gs_lib_ctx_core_t *core;
+
+ if (ctx == NULL || ctx->core == NULL || argv == NULL)
+ return 0;
+
+ core = ctx->core;
+ *argv = core->argv;
+ return core->argc;
+}