diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2022-08-26 10:07:22 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2022-08-26 10:07:22 +0100 |
commit | ee290c1aebaa172c812f21024af2dbf721fa5865 (patch) | |
tree | 3a622d1ebddf5406e0a84ece0fb8a4cd79928f09 /psi | |
parent | 19c421c10385b89da8564d664c2c5679c7558035 (diff) | |
download | ghostpdl-ee290c1aebaa172c812f21024af2dbf721fa5865.tar.gz |
graphics library - prevent seg fault in .tempfile
Coverity ID #380524
A seg fault can be reproduced on Windows using this PostScript:
(d:\\temp) (w+) .tempfile
The problem occurs because on Windows gp_file_name_is_absolute permits
either '\' or '/' to be used as a separator, but gp_file_name_separator
can (obviously) only return one separator, in this case '/'.
This means the loop stripping the prefix fails to find any separator
and exits with plen = -1, which causes a seg fault in the memcpy below.
The first part of the fix is to check plen and if it's less than 0
exit with an error.
The remainder of the commit changes from using the separator string to
calling gp_file_name_check_separator instead. This has two benefits;
firstly it means that on Windows both separators can be detected,
secondly for OS's where the separator is more than a single byte we can
still detect it, which we could not before.
Ghostscript itself never uses .tempfile with a filename, so this can
only occur with PostScript input.
Diffstat (limited to 'psi')
-rw-r--r-- | psi/zfile.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/psi/zfile.c b/psi/zfile.c index fe3f7e9f9..e4a2a3e17 100644 --- a/psi/zfile.c +++ b/psi/zfile.c @@ -772,18 +772,25 @@ ztempfile(i_ctx_t *i_ctx_p) if (gp_file_name_is_absolute(pstr, strlen(pstr))) { int plen = strlen(pstr); const char *sep = gp_file_name_separator(); -#ifdef DEBUG int seplen = strlen(sep); - if (seplen != 1) + + /* This should not be possible if gp_file_name_is_absolute is true I think + * But let's avoid the problem. + */ + if (plen < seplen) return_error(gs_error_Fatal); -#endif + + plen -= seplen; /* strip off the file name prefix, leave just the directory name * so we can check if we are allowed to write to it */ for ( ; plen >=0; plen--) { - if (pstr[plen] == sep[0]) + if ( gs_file_name_check_separator(&pstr[plen], seplen, &pstr[plen])) break; } + if (plen < 0) + return_error(gs_error_Fatal); + memcpy(fname, pstr, plen); fname[plen] = '\0'; if (check_file_permissions(i_ctx_p, fname, strlen(fname), |