summaryrefslogtreecommitdiff
path: root/base/gslibctx.c
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2020-08-17 15:44:01 +0100
committerRobin Watts <Robin.Watts@artifex.com>2020-08-18 18:48:38 +0100
commit9619c8fc8d1e2548c737adfb7f6b8b15d49d20a4 (patch)
tree66996b49c28966cbb003ad260b236726768a676a /base/gslibctx.c
parentdf245b46c1a5290239b2932e2a5d1bdeae710c48 (diff)
downloadghostpdl-9619c8fc8d1e2548c737adfb7f6b8b15d49d20a4.tar.gz
Bug 702744: Add windows utf-8 handling for unlink and rename.
To do this, we introduce gp_unlink and gp_rename, and call those as appropriate. Also, make gp_open_scratch_file add the file to the permit list. When such a file is closed, it will be deleted from the permit list. It will also be removed from the permit list if the file is deleted using the PS deletefile operator. On closedown, if scratch files haven't been deleted, then we'll delete them as part of the closedown of gs_lib_ctx. This means that 'purging' the control lists must not remove scratch file paths from the list. Also, ensure that gsapi callers can't maliciously (or accidentally) remove scratch path paths from the list so as to leave them around after closedown.
Diffstat (limited to 'base/gslibctx.c')
-rw-r--r--base/gslibctx.c130
1 files changed, 107 insertions, 23 deletions
diff --git a/base/gslibctx.c b/base/gslibctx.c
index 5b585e8e0..d726c58b5 100644
--- a/base/gslibctx.c
+++ b/base/gslibctx.c
@@ -420,6 +420,7 @@ void gs_lib_ctx_fin(gs_memory_t *mem)
#ifdef WITH_CAL
cal_fin(ctx->core->cal_ctx, ctx->core->memory);
#endif
+ gs_purge_scratch_files(ctx->core->memory);
gs_purge_control_paths(ctx->core->memory, gs_permit_file_reading);
gs_purge_control_paths(ctx->core->memory, gs_permit_file_writing);
gs_purge_control_paths(ctx->core->memory, gs_permit_file_control);
@@ -735,6 +736,12 @@ gs_add_explicit_control_path(gs_memory_t *mem, const char *arg, gs_path_control_
int
gs_add_control_path_len(const gs_memory_t *mem, gs_path_control_t type, const char *path, size_t len)
{
+ return gs_add_control_path_len_flags(mem, type, path, len, 0);
+}
+
+int
+gs_add_control_path_len_flags(const gs_memory_t *mem, gs_path_control_t type, const char *path, size_t len, int flags)
+{
gs_path_control_set_t *control;
unsigned int n, i;
gs_lib_ctx_core_t *core;
@@ -774,33 +781,34 @@ gs_add_control_path_len(const gs_memory_t *mem, gs_path_control_t type, const ch
n = control->num;
for (i = 0; i < n; i++)
{
- if (strncmp(control->paths[i], buffer, rlen) == 0 &&
- control->paths[i][rlen] == 0) {
+ if (strncmp(control->entry[i].path, buffer, rlen) == 0 &&
+ control->entry[i].path[rlen] == 0) {
gs_free_object(core->memory, buffer, "gs_add_control_path_len");
return 0; /* Already there! */
}
}
if (control->num == control->max) {
- char **p;
+ gs_path_control_entry_t *p;
n = control->max * 2;
if (n == 0) {
n = 4;
- p = (char **)gs_alloc_bytes(core->memory, sizeof(*p)*n, "gs_lib_ctx(paths)");
+ p = (gs_path_control_entry_t *)gs_alloc_bytes(core->memory, sizeof(*p)*n, "gs_lib_ctx(entries)");
} else
- p = (char **)gs_resize_object(core->memory, control->paths, sizeof(*p)*n, "gs_lib_ctx(paths)");
+ p = (gs_path_control_entry_t *)gs_resize_object(core->memory, control->entry, sizeof(*p)*n, "gs_lib_ctx(entries)");
if (p == NULL) {
gs_free_object(core->memory, buffer, "gs_add_control_path_len");
return gs_error_VMerror;
}
- control->paths = p;
+ control->entry = p;
control->max = n;
}
n = control->num;
- control->paths[n] = buffer;
- control->paths[n][len] = 0;
+ control->entry[n].path = buffer;
+ control->entry[n].path[len] = 0;
+ control->entry[n].flags = flags;
control->num++;
return 0;
@@ -809,15 +817,24 @@ gs_add_control_path_len(const gs_memory_t *mem, gs_path_control_t type, const ch
int
gs_add_control_path(const gs_memory_t *mem, gs_path_control_t type, const char *path)
{
- if (path == NULL)
- return 0;
+ return gs_add_control_path_len_flags(mem, type, path, strlen(path), 0);
+}
- return gs_add_control_path_len(mem, type, path, strlen(path));
+int
+gs_add_control_path_flags(const gs_memory_t *mem, gs_path_control_t type, const char *path, int flags)
+{
+ return gs_add_control_path_len_flags(mem, type, path, strlen(path), flags);
}
int
gs_remove_control_path_len(const gs_memory_t *mem, gs_path_control_t type, const char *path, size_t len)
{
+ return gs_remove_control_path_len_flags(mem, type, path, len, 0);
+}
+
+int
+gs_remove_control_path_len_flags(const gs_memory_t *mem, gs_path_control_t type, const char *path, size_t len, int flags)
+{
gs_path_control_set_t *control;
unsigned int n, i;
gs_lib_ctx_core_t *core;
@@ -856,17 +873,18 @@ gs_remove_control_path_len(const gs_memory_t *mem, gs_path_control_t type, const
n = control->num;
for (i = 0; i < n; i++) {
- if (strncmp(control->paths[i], buffer, len) == 0 &&
- control->paths[i][len] == 0)
+ if (control->entry[i].flags == flags &&
+ strncmp(control->entry[i].path, buffer, len) == 0 &&
+ control->entry[i].path[len] == 0)
break;
}
gs_free_object(core->memory, buffer, "gs_remove_control_path_len");
if (i == n)
return 0;
- gs_free_object(core->memory, control->paths[i], "gs_lib_ctx(path)");
+ gs_free_object(core->memory, control->entry[i].path, "gs_lib_ctx(path)");
for (;i < n-1; i++)
- control->paths[i] = control->paths[i+1];
+ control->entry[i] = control->entry[i+1];
control->num = n-1;
return 0;
@@ -878,14 +896,23 @@ gs_remove_control_path(const gs_memory_t *mem, gs_path_control_t type, const cha
if (path == NULL)
return 0;
- return gs_remove_control_path_len(mem, type, path, strlen(path));
+ return gs_remove_control_path_len_flags(mem, type, path, strlen(path), 0);
+}
+
+int
+gs_remove_control_path_flags(const gs_memory_t *mem, gs_path_control_t type, const char *path, int flags)
+{
+ if (path == NULL)
+ return 0;
+
+ return gs_remove_control_path_len_flags(mem, type, path, strlen(path), flags);
}
void
gs_purge_control_paths(const gs_memory_t *mem, gs_path_control_t type)
{
gs_path_control_set_t *control;
- unsigned int n, i;
+ unsigned int n, in, out;
gs_lib_ctx_core_t *core;
if (mem == NULL || mem->gs_lib_ctx == NULL ||
@@ -907,13 +934,70 @@ gs_purge_control_paths(const gs_memory_t *mem, gs_path_control_t type)
}
n = control->num;
- for (i = 0; i < n; i++) {
- gs_free_object(core->memory, control->paths[i], "gs_lib_ctx(path)");
+ for (in = out = 0; in < n; in++) {
+ if (control->entry[in].flags & gs_path_control_flag_is_scratch_file) {
+ /* Don't purge scratch files! */
+ control->entry[out++] = control->entry[in];
+ } else
+ gs_free_object(core->memory, control->entry[in].path, "gs_lib_ctx(path)");
+ }
+ control->num = out;
+ if (out == 0) {
+ gs_free_object(core->memory, control->entry, "gs_lib_ctx(paths)");
+ control->entry = NULL;
+ control->max = 0;
+ }
+}
+
+void
+gs_purge_scratch_files(const gs_memory_t *mem)
+{
+ gs_path_control_set_t *control;
+ gs_path_control_t type;
+ int n, in, out;
+ gs_lib_ctx_core_t *core;
+
+ if (mem == NULL || mem->gs_lib_ctx == NULL ||
+ (core = mem->gs_lib_ctx->core) == NULL)
+ return;
+
+ for (type = gs_permit_file_reading; type <= gs_permit_file_control; type++)
+ {
+ switch(type) {
+ default:
+ case gs_permit_file_reading:
+ control = &core->permit_reading;
+ break;
+ case gs_permit_file_writing:
+ control = &core->permit_writing;
+ break;
+ case gs_permit_file_control:
+ control = &core->permit_control;
+ break;
+ }
+
+ n = control->num;
+ for (in = out = 0; in < n; in++) {
+ if ((control->entry[in].flags & gs_path_control_flag_is_scratch_file) == 0) {
+ /* Only purge scratch files! */
+ control->entry[out++] = control->entry[in];
+ } else {
+ if (type == gs_permit_file_reading) {
+ /* Call gp_unlink_impl, as we don't want gp_unlink
+ * to go looking in the lists we are currently
+ * manipulating! */
+ gp_unlink_impl(core->memory, control->entry[in].path);
+ }
+ gs_free_object(core->memory, control->entry[in].path, "gs_lib_ctx(path)");
+ }
+ }
+ control->num = out;
+ if (out == 0) {
+ gs_free_object(core->memory, control->entry, "gs_lib_ctx(paths)");
+ control->entry = NULL;
+ control->max = 0;
+ }
}
- gs_free_object(core->memory, control->paths, "gs_lib_ctx(paths)");
- control->paths = NULL;
- control->num = 0;
- control->max = 0;
}
void