Commit message: None
CVE: CVE-2018-16863
CWE: CWE-78
Vulnerability description: It was found that RHSA-2018:2918 did not fully fix CVE-2018-16509. An attacker could possibly exploit another variant of the flaw and bypass the -dSAFER protection to, for example, execute arbitrary shell commands via a specially crafted PostScript document. This only affects ghostscript 9.07 as shipped with Red Hat Enterprise Linux 7.

Project: ghostscript

gs_copydevice(gx_device ** pnew_dev, const gx_device * dev, gs_memory_t * mem)
{
    return gs_copydevice2(pnew_dev, dev, false, mem);
}

Project: ghostscript

gs_devicename(const gx_device * dev)
{
    return dev->dname;
}

Project: ghostscript

bool gs_is_null_device(gx_device *dev)
{
    /* Assuming null_fill_path isn't used elswhere. */
    return dev->procs.fill_path == gs_null_device.procs.fill_path;
}

Project: ghostscript

gx_device_adjust_resolution(gx_device * dev,
                            int actual_width, int actual_height, int fit)
{
    double width_ratio = (double)actual_width / dev->width;
    double height_ratio = (double)actual_height / dev->height;
    double ratio =
    (fit ? min(width_ratio, height_ratio) :
     max(width_ratio, height_ratio));

    dev->HWResolution[0] *= ratio;
    dev->HWResolution[1] *= ratio;
    gx_device_set_width_height(dev, actual_width, actual_height);
    return 0;
}

Project: ghostscript

gx_device_close_output_file(const gx_device * dev, const char *fname,
                            FILE *file)
{
    gs_parsed_file_name_t parsed;
    const char *fmt;
    int code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname),
                                         dev->memory);

    if (code < 0)
        return code;
    if (parsed.iodev) {
        if (!strcmp(parsed.iodev->dname, "%stdout%"))
            return 0;
        /* NOTE: fname is unsubstituted if the name has any %nnd formats. */
        if (parsed.iodev != iodev_default(dev->memory))
            return parsed.iodev->procs.fclose(parsed.iodev, file);
    }
    gp_close_printer(dev->memory, file, (parsed.fname ? parsed.fname : fname));
    return 0;
}

Project: ghostscript

gx_device_init(gx_device * dev, const gx_device * proto, gs_memory_t * mem,
               bool internal)
{
    memcpy(dev, proto, proto->params_size);
    dev->memory = mem;
    dev->retained = !internal;
    rc_init(dev, mem, (internal ? 0 : 1));
    rc_increment(dev->icc_struct);
}

Project: ghostscript

gx_device_init_on_stack(gx_device * dev, const gx_device * proto,
                        gs_memory_t * mem)
{
    memcpy(dev, proto, proto->params_size);
    dev->memory = mem;
    dev->retained = 0;
    dev->pad = proto->pad;
    dev->log2_align_mod = proto->log2_align_mod;
    dev->is_planar = proto->is_planar;
    rc_init(dev, NULL, 0);
}

Project: ghostscript

gx_device_raster_chunky(const gx_device * dev, bool pad)
{
    ulong bits = (ulong) dev->width * dev->color_info.depth;
    ulong raster;
    int l2align;

    raster = (uint)((bits + 7) >> 3);
    if (!pad)
        return raster;
    l2align = dev->log2_align_mod;
    if (l2align < log2_align_bitmap_mod)
        l2align = log2_align_bitmap_mod;
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
}

Project: ghostscript

gx_device_raster_plane(const gx_device * dev, const gx_render_plane_t *render_plane)
{
    ulong bpc = (render_plane && render_plane->index >= 0 ?
        render_plane->depth : dev->color_info.depth/(dev->is_planar ? dev->color_info.num_components : 1));
    ulong bits = (ulong) dev->width * bpc;
    int l2align;

    l2align = dev->log2_align_mod;
    if (l2align < log2_align_bitmap_mod)
        l2align = log2_align_bitmap_mod;
    return (uint)(((bits + (8 << l2align) - 1) >> (l2align + 3)) << l2align);
}

Project: ghostscript

gx_parse_output_file_name(gs_parsed_file_name_t *pfn, const char **pfmt,
                          const char *fname, uint fnlen, gs_memory_t *memory)
{
    int code;

    *pfmt = 0;
    pfn->memory = 0;
    pfn->iodev = NULL;
    pfn->fname = NULL;		/* irrelevant since length = 0 */
    pfn->len = 0;
    if (fnlen == 0)  		/* allow null name */
        return 0;
    /*
     * If the file name begins with a %, it might be either an IODevice
     * or a %nnd format.  Check (carefully) for this case.
     */
    code = gs_parse_file_name(pfn, fname, fnlen, memory);
    if (code < 0) {
        if (fname[0] == '%') {
            /* not a recognized iodev -- may be a leading format descriptor */
            pfn->len = fnlen;
            pfn->fname = fname;
            code = gx_parse_output_format(pfn, pfmt);
        }
        if (code < 0)
            return code;
    }
    if (!pfn->iodev) {
        if ( (pfn->len == 1) && (pfn->fname[0] == '-') ) {
            pfn->iodev = gs_findiodevice(memory, (const byte *)"%stdout", 7);
            pfn->fname = NULL;
        } else if (pfn->fname[0] == '|') {
            pfn->iodev = gs_findiodevice(memory, (const byte *)"%pipe", 5);
            pfn->fname++, pfn->len--;
        } else
            pfn->iodev = iodev_default(memory);
        if (!pfn->iodev)
            return_error(gs_error_undefinedfilename);
    }
    if (!pfn->fname)
        return 0;
    code = gx_parse_output_format(pfn, pfmt);
    if (code < 0)
        return code;
    if (strlen(pfn->iodev->dname) + pfn->len + code >= gp_file_name_sizeof)
        return_error(gs_error_undefinedfilename);
    return 0;
}