Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/sjpegc.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Interface routines for IJG code, common to encode/decode. */
18
#include "stdio_.h"
19
#include "string_.h"
20
#include "jpeglib_.h"
21
#include "jerror_.h"
22
#include "gx.h"
23
#include "gserrors.h"
24
#include "strimpl.h"
25
#include "sdct.h"
26
#include "sjpeg.h"
27
#include "gsmchunk.h"
28
29
#if !defined(SHARE_JPEG) || SHARE_JPEG==0
30
#include "jmemcust.h"
31
#endif
32
33
/*
34
  Ghostscript uses a non-public interface to libjpeg in order to
35
  override the library's default memory manager implementation.
36
  Since many users will want to compile Ghostscript using the
37
  shared jpeg library, we provide these prototypes so that a copy
38
  of the libjpeg source distribution is not needed.
39
40
  The presence of the jmemsys.h header file is detected in
41
  unix-aux.mak, and written to gconfig_.h
42
 */
43
44
#include "gconfig_.h"
45
46
/*
47
 * Error handling routines (these replace corresponding IJG routines from
48
 * jpeg/jerror.c).  These are used for both compression and decompression.
49
 * We assume
50
 * offset_of(jpeg_compress_data, cinfo)==offset_of(jpeg_decompress_data, dinfo)
51
 */
52
53
static void
54
gs_jpeg_error_exit(j_common_ptr cinfo)
55
1.40k
{
56
1.40k
    jpeg_stream_data *jcomdp =
57
1.40k
    (jpeg_stream_data *) ((char *)cinfo -
58
1.40k
                          offset_of(jpeg_compress_data, cinfo));
59
60
1.40k
    longjmp(find_jmp_buf(jcomdp->exit_jmpbuf), 1);
61
1.40k
}
62
63
static void
64
gs_jpeg_emit_message(j_common_ptr cinfo, int msg_level)
65
199k
{
66
199k
    if (msg_level < 0) { /* GS policy is to ignore IJG warnings when Picky=0,
67
                                 * treat them as errors when Picky=1.
68
                                 */
69
13.0k
        jpeg_stream_data *jcomdp =
70
13.0k
        (jpeg_stream_data *) ((char *)cinfo -
71
13.0k
                              offset_of(jpeg_compress_data, cinfo));
72
73
13.0k
        if (jcomdp->Picky)
74
0
            gs_jpeg_error_exit(cinfo);
75
13.0k
    }
76
    /* Trace messages are always ignored. */
77
199k
}
78
79
/*
80
 * This routine initializes the error manager fields in the JPEG object.
81
 * It is based on jpeg_std_error from jpeg/jerror.c.
82
 */
83
84
void
85
gs_jpeg_error_setup(stream_DCT_state * st)
86
384k
{
87
384k
    struct jpeg_error_mgr *err = &st->data.common->err;
88
89
    /* Initialize the JPEG compression object with default error handling */
90
384k
    jpeg_std_error(err);
91
92
    /* Replace some methods with our own versions */
93
384k
    err->error_exit = gs_jpeg_error_exit;
94
384k
    err->emit_message = gs_jpeg_emit_message;
95
96
384k
    st->data.compress->cinfo.err = err;   /* works for decompress case too */
97
384k
}
98
99
/* Stuff the IJG error message into errorinfo after an error exit. */
100
101
int
102
gs_jpeg_log_error(stream_DCT_state * st)
103
1.40k
{
104
1.40k
    j_common_ptr cinfo = (j_common_ptr) & st->data.compress->cinfo;
105
1.40k
    char buffer[JMSG_LENGTH_MAX];
106
107
    /* Format the error message */
108
1.40k
    (*cinfo->err->format_message) (cinfo, buffer);
109
1.40k
    (*st->report_error) ((stream_state *) st, buffer);
110
1.40k
    return_error(gs_error_ioerror); /* caller will do return_error() */
111
1.40k
}
112
113
/*
114
 * Interface routines.  This layer of routines exists solely to limit
115
 * side-effects from using setjmp.
116
 */
117
118
JQUANT_TBL *
119
gs_jpeg_alloc_quant_table(stream_DCT_state * st)
120
0
{
121
0
    if (setjmp(find_jmp_buf(st->data.common->exit_jmpbuf))) {
122
0
        gs_jpeg_log_error(st);
123
0
        return NULL;
124
0
    }
125
0
    return jpeg_alloc_quant_table((j_common_ptr)
126
0
                                  & st->data.compress->cinfo);
127
0
}
128
129
JHUFF_TBL *
130
gs_jpeg_alloc_huff_table(stream_DCT_state * st)
131
0
{
132
0
    if (setjmp(find_jmp_buf(st->data.common->exit_jmpbuf))) {
133
0
        gs_jpeg_log_error(st);
134
0
        return NULL;
135
0
    }
136
0
    return jpeg_alloc_huff_table((j_common_ptr)
137
0
                                 & st->data.compress->cinfo);
138
0
}
139
140
int
141
gs_jpeg_destroy(stream_DCT_state * st)
142
384k
{
143
384k
    if (st->data.common && setjmp(find_jmp_buf(st->data.common->exit_jmpbuf)))
144
0
        return_error(gs_jpeg_log_error(st));
145
146
384k
    if (st->data.compress){
147
384k
        jpeg_destroy((j_common_ptr) & st->data.compress->cinfo);
148
384k
        gs_jpeg_mem_term((j_common_ptr) & st->data.compress->cinfo);
149
384k
    }
150
384k
    return 0;
151
384k
}
152
153
#if !defined(SHARE_JPEG) || SHARE_JPEG==0
154
static void *gs_j_mem_alloc(j_common_ptr cinfo, size_t size)
155
809k
{
156
809k
    gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv);
157
158
809k
    return(gs_alloc_bytes(mem, size, "JPEG allocation"));
159
809k
}
160
161
static void gs_j_mem_free(j_common_ptr cinfo, void *object, size_t size)
162
809k
{
163
809k
    gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv);
164
165
809k
    gs_free_object(mem, object, "JPEG free");
166
809k
}
167
168
static long gs_j_mem_init (j_common_ptr cinfo)
169
384k
{
170
384k
    gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv);
171
384k
    gs_memory_t *cmem = NULL;
172
173
384k
    if (gs_memory_chunk_wrap(&(cmem), mem) < 0) {
174
0
        return (-1);
175
0
    }
176
177
384k
    (void)jpeg_cust_mem_set_private(GET_CUST_MEM_DATA(cinfo), cmem);
178
179
384k
    return 0;
180
384k
}
181
182
static void gs_j_mem_term (j_common_ptr cinfo)
183
384k
{
184
384k
    gs_memory_t *cmem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv);
185
384k
    gs_memory_t *mem = gs_memory_chunk_unwrap(cmem);
186
187
384k
    if (mem == cmem)
188
0
        return;
189
190
384k
    (void)jpeg_cust_mem_set_private(GET_CUST_MEM_DATA(cinfo), mem);
191
384k
}
192
#endif /* SHAREJPEG == 0 */
193
194
195
int gs_jpeg_mem_init (gs_memory_t *mem, j_common_ptr cinfo)
196
384k
{
197
384k
    int code = 0;
198
384k
#if !defined(SHARE_JPEG) || SHARE_JPEG==0
199
384k
    jpeg_cust_mem_data custm, *custmptr;
200
201
384k
    memset(&custm, 0x00, sizeof(custm));
202
203
    /* JPEG allocated chunks don't need to be subject to gc. */
204
384k
    mem = mem->non_gc_memory;
205
206
384k
    if (!jpeg_cust_mem_init(&custm, (void *) mem, gs_j_mem_init, gs_j_mem_term, NULL,
207
384k
                            gs_j_mem_alloc, gs_j_mem_free,
208
384k
                            gs_j_mem_alloc, gs_j_mem_free, NULL)) {
209
0
        code = gs_note_error(gs_error_VMerror);
210
0
    }
211
384k
    if (code == 0) {
212
384k
        custmptr = (jpeg_cust_mem_data *)gs_alloc_bytes(mem, sizeof(custm) + sizeof(void *), "JPEG custom memory descriptor");
213
384k
        if (!custmptr) {
214
0
            code = gs_note_error(gs_error_VMerror);
215
0
        }
216
384k
        else {
217
384k
            memcpy(custmptr, &custm, sizeof(custm));
218
384k
            cinfo->client_data = custmptr;
219
384k
        }
220
384k
    }
221
384k
#endif /* SHAREJPEG == 0 */
222
384k
    return code;
223
384k
}
224
225
void
226
gs_jpeg_mem_term(j_common_ptr cinfo)
227
384k
{
228
384k
#if !defined(SHARE_JPEG) || SHARE_JPEG==0
229
384k
    if (cinfo->client_data) {
230
384k
        jpeg_cust_mem_data *custmptr = (jpeg_cust_mem_data *)cinfo->client_data;
231
384k
        gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv);
232
233
384k
        gs_free_object(mem, custmptr, "gs_jpeg_mem_term");
234
384k
        cinfo->client_data = NULL;
235
384k
    }
236
384k
#endif /* SHAREJPEG == 0 */
237
384k
}