~ubuntu-branches/ubuntu/precise/devil/precise

« back to all changes in this revision

Viewing changes to src-IL/src/il_jp2.c

  • Committer: Bazaar Package Importer
  • Author(s): Bradley Smith
  • Date: 2009-01-17 15:01:18 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090117150118-4bwb6nmvbz4srsjl
Tags: 1.7.5-4
Actually fix CVE-2008-5262. Closes: #512122.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//-----------------------------------------------------------------------------
 
2
//
 
3
// ImageLib Sources
 
4
// Copyright (C) 2000-2008 by Denton Woods
 
5
// Last modified: 08/24/2008
 
6
//
 
7
// Filename: src-IL/src/il_jp2.c
 
8
//
 
9
// Description: Jpeg-2000 (.jp2) functions
 
10
//
 
11
//-----------------------------------------------------------------------------
 
12
 
 
13
 
 
14
// @TODO:  Look in jas_stream.c of JasPer and make own version of
 
15
//  jas_stream_fopen that will return a jas_stream_t and
 
16
//  work on file streams instead of just a filename.
 
17
 
 
18
#include "il_internal.h"
 
19
#ifndef IL_NO_JP2
 
20
#include <jasper/jasper.h>
 
21
#include "il_jp2.h"
 
22
 
 
23
#if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS)
 
24
        #if defined(_MSC_VER) || defined(__BORLANDC__)
 
25
                #ifndef _DEBUG
 
26
                        #pragma comment(lib, "libjasper.lib")
 
27
                #else
 
28
                        #pragma comment(lib, "libjasper-d.lib")
 
29
                #endif
 
30
        #endif
 
31
#endif
 
32
 
 
33
 
 
34
//! Reads a Jpeg2000 file.
 
35
ILboolean ilLoadJp2(ILconst_string FileName)
 
36
{
 
37
        ILHANDLE        Jp2File;
 
38
        ILboolean       bRet;
 
39
 
 
40
        Jp2File = iopenr(FileName);
 
41
        if (Jp2File == NULL) {
 
42
                ilSetError(IL_COULD_NOT_OPEN_FILE);
 
43
                return IL_FALSE;
 
44
        }
 
45
 
 
46
        bRet = ilLoadJp2F(Jp2File);
 
47
        icloser(Jp2File);
 
48
 
 
49
        return bRet;
 
50
}
 
51
 
 
52
 
 
53
//! Reads an already-opened Jpeg2000 file.
 
54
ILboolean ilLoadJp2F(ILHANDLE File)
 
55
{
 
56
        ILuint                  FirstPos;
 
57
        ILboolean               bRet;
 
58
        jas_stream_t    *Stream;
 
59
 
 
60
        iSetInputFile(File);
 
61
        FirstPos = itell();
 
62
 
 
63
        if (jas_init())
 
64
        {
 
65
                ilSetError(IL_LIB_JP2_ERROR);
 
66
                return IL_FALSE;
 
67
        }
 
68
        Stream = iJp2ReadStream();
 
69
        if (!Stream)
 
70
        {
 
71
                ilSetError(IL_COULD_NOT_OPEN_FILE);
 
72
                return IL_FALSE;
 
73
        }
 
74
 
 
75
        bRet = iLoadJp2Internal(Stream, NULL);
 
76
        // Close the input stream.
 
77
        jas_stream_close(Stream);
 
78
 
 
79
        iseek(FirstPos, IL_SEEK_SET);
 
80
 
 
81
        return bRet;
 
82
}
 
83
 
 
84
 
 
85
//! Reads from a memory "lump" that contains a Jpeg2000 stream.
 
86
ILboolean ilLoadJp2L(const void *Lump, ILuint Size)
 
87
{
 
88
        return ilLoadJp2LInternal(Lump, Size, NULL);
 
89
}
 
90
 
 
91
 
 
92
//! This is separated so that it can be called for other file types, such as .icns.
 
93
ILboolean ilLoadJp2LInternal(const void *Lump, ILuint Size, ILimage *Image)
 
94
{
 
95
        ILboolean               bRet;
 
96
        jas_stream_t    *Stream;
 
97
 
 
98
        if (jas_init())
 
99
        {
 
100
                ilSetError(IL_LIB_JP2_ERROR);
 
101
                return IL_FALSE;
 
102
        }
 
103
        Stream = jas_stream_memopen((char*)Lump, Size);
 
104
        if (!Stream)
 
105
        {
 
106
                ilSetError(IL_COULD_NOT_OPEN_FILE);
 
107
                return IL_FALSE;
 
108
        }
 
109
 
 
110
        bRet = iLoadJp2Internal(Stream, Image);
 
111
        // Close the input stream.
 
112
        jas_stream_close(Stream);
 
113
 
 
114
        return bRet;
 
115
}
 
116
 
 
117
 
 
118
// Internal function used to load the Jpeg2000 stream.
 
119
ILboolean iLoadJp2Internal(jas_stream_t *Stream, ILimage *Image)
 
120
{
 
121
        jas_image_t             *Jp2Image = NULL;
 
122
        jas_matrix_t    *origdata;
 
123
        ILuint                  x, y, c;
 
124
        ILimage                 *TempImage;
 
125
 
 
126
        // Decode image
 
127
        Jp2Image = jas_image_decode(Stream, -1, 0);
 
128
        if (!Jp2Image)
 
129
        {
 
130
                ilSetError(IL_ILLEGAL_FILE_VALUE);
 
131
                jas_stream_close(Stream);
 
132
                return IL_FALSE;
 
133
        }
 
134
 
 
135
        // We're not supporting anything other than 8 bits/component yet.
 
136
        if (jas_image_cmptprec(Jp2Image, 0) != 8)
 
137
        {
 
138
                jas_image_destroy(Jp2Image);
 
139
                ilSetError(IL_ILLEGAL_FILE_VALUE);
 
140
                return IL_FALSE;
 
141
        }
 
142
 
 
143
        switch (jas_image_numcmpts(Jp2Image))
 
144
        {
 
145
                case 3:
 
146
                        if (Image == NULL) {
 
147
                                ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL);
 
148
                                TempImage = iCurImage;
 
149
                        }
 
150
                        else {
 
151
                                ifree(Image->Data);  // @TODO: Not really the most efficient way to do this...
 
152
                                ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL);
 
153
                                TempImage = Image;
 
154
                        }
 
155
                        break;
 
156
                case 4:
 
157
                        if (Image == NULL) {
 
158
                                ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
 
159
                                TempImage = iCurImage;
 
160
                        }
 
161
                        else {
 
162
                                ifree(Image->Data);  // @TODO: Not really the most efficient way to do this...
 
163
                                ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
 
164
                                TempImage = Image;
 
165
                        }
 
166
                        break;
 
167
                default:
 
168
                        jas_image_destroy(Jp2Image);
 
169
                        ilSetError(IL_ILLEGAL_FILE_VALUE);
 
170
                        return IL_FALSE;
 
171
        }
 
172
        TempImage->Origin = IL_ORIGIN_UPPER_LEFT;
 
173
 
 
174
        // JasPer stores the data channels separately.
 
175
        //  I am assuming RGBA format.  Is it possible for other formats to be included?
 
176
        for (c = 0; c < TempImage->Bpp; c++)
 
177
        {
 
178
                origdata = jas_matrix_create(TempImage->Height, TempImage->Width);
 
179
                if (!origdata)
 
180
                {
 
181
                        ilSetError(IL_LIB_JP2_ERROR);
 
182
                        return IL_FALSE;  // @TODO: Error
 
183
                }
 
184
                // Have to convert data into an intermediate matrix format.
 
185
                if (jas_image_readcmpt(Jp2Image, c, 0, 0, TempImage->Width, TempImage->Height, origdata))
 
186
                {
 
187
                        return IL_FALSE;
 
188
                }
 
189
 
 
190
                for (y = 0; y < TempImage->Height; y++)
 
191
                {
 
192
                        for (x = 0; x < TempImage->Width; x++)
 
193
                        {
 
194
                                TempImage->Data[y * TempImage->Width * TempImage->Bpp + x * TempImage->Bpp + c] = origdata->data_[y * origdata->numcols_ + x];
 
195
                        }
 
196
                }
 
197
 
 
198
                jas_matrix_destroy(origdata);
 
199
        }
 
200
 
 
201
        jas_image_destroy(Jp2Image);
 
202
 
 
203
        ilFixImage();
 
204
 
 
205
        return IL_TRUE;
 
206
}
 
207
 
 
208
 
 
209
 
 
210
static int iJp2_file_read(jas_stream_obj_t *obj, char *buf, int cnt)
 
211
{
 
212
        obj;
 
213
        return iread(buf, 1, cnt);
 
214
}
 
215
 
 
216
static int iJp2_file_write(jas_stream_obj_t *obj, char *buf, int cnt)
 
217
{
 
218
        obj;
 
219
        return iwrite(buf, 1, cnt);
 
220
}
 
221
 
 
222
static long iJp2_file_seek(jas_stream_obj_t *obj, long offset, int origin)
 
223
{
 
224
        obj;
 
225
 
 
226
        // We could just pass origin to iseek, but this is probably more portable.
 
227
        switch (origin)
 
228
        {
 
229
                case SEEK_SET:
 
230
                        return iseek(offset, IL_SEEK_SET);
 
231
                case SEEK_CUR:
 
232
                        return iseek(offset, IL_SEEK_CUR);
 
233
                case SEEK_END:
 
234
                        return iseek(offset, IL_SEEK_END);
 
235
        }
 
236
        return 0;  // Failed
 
237
}
 
238
 
 
239
static int iJp2_file_close(jas_stream_obj_t *obj)
 
240
{
 
241
        obj;
 
242
        return 0;  // We choose when we want to close the file.
 
243
}
 
244
 
 
245
static jas_stream_ops_t jas_stream_devilops = {
 
246
        iJp2_file_read,
 
247
        iJp2_file_write,
 
248
        iJp2_file_seek,
 
249
        iJp2_file_close
 
250
};
 
251
 
 
252
static jas_stream_t *jas_stream_create(void);
 
253
static void jas_stream_destroy(jas_stream_t *stream);
 
254
static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf, int bufsize);
 
255
 
 
256
 
 
257
// Modified version of jas_stream_fopen and jas_stream_memopen from jas_stream.c of JasPer
 
258
//  so that we can use our own file routines.
 
259
jas_stream_t *iJp2ReadStream()
 
260
{
 
261
        jas_stream_t *stream;
 
262
        jas_stream_memobj_t *obj;
 
263
 
 
264
        if (!(stream = jas_stream_create())) {
 
265
                return 0;
 
266
        }
 
267
 
 
268
        /* A stream associated with a memory buffer is always opened
 
269
        for both reading and writing in binary mode. */
 
270
        stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_BINARY;
 
271
 
 
272
        /* We use buffering whether it is from memory or a file. */
 
273
        jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
 
274
 
 
275
        /* Select the operations for a memory stream. */
 
276
        stream->ops_ = &jas_stream_devilops;
 
277
 
 
278
        /* Allocate memory for the underlying memory stream object. */
 
279
        if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) {
 
280
                jas_stream_destroy(stream);
 
281
                return 0;
 
282
        }
 
283
        stream->obj_ = (void *) obj;
 
284
 
 
285
        /* Initialize a few important members of the memory stream object. */
 
286
        obj->myalloc_ = 0;
 
287
        obj->buf_ = 0;
 
288
 
 
289
        // Shouldn't need any of this.
 
290
 
 
291
        ///* If the buffer size specified is nonpositive, then the buffer
 
292
        //is allocated internally and automatically grown as needed. */
 
293
        //if (bufsize <= 0) {
 
294
        //      obj->bufsize_ = 1024;
 
295
        //      obj->growable_ = 1;
 
296
        //} else {
 
297
        //      obj->bufsize_ = bufsize;
 
298
        //      obj->growable_ = 0;
 
299
        //}
 
300
        //if (buf) {
 
301
        //      obj->buf_ = (unsigned char *) buf;
 
302
        //} else {
 
303
        //      obj->buf_ = jas_malloc(obj->bufsize_ * sizeof(char));
 
304
        //      obj->myalloc_ = 1;
 
305
        //}
 
306
        //if (!obj->buf_) {
 
307
        //      jas_stream_close(stream);
 
308
        //      return 0;
 
309
        //}
 
310
 
 
311
        //if (bufsize > 0 && buf) {
 
312
        //      /* If a buffer was supplied by the caller and its length is positive,
 
313
        //        make the associated buffer data appear in the stream initially. */
 
314
        //      obj->len_ = bufsize;
 
315
        //} else {
 
316
        //      /* The stream is initially empty. */
 
317
        //      obj->len_ = 0;
 
318
        //}
 
319
        //obj->pos_ = 0;
 
320
        
 
321
        return stream;
 
322
}
 
323
 
 
324
 
 
325
// The following functions are taken directly from jas_stream.c of JasPer,
 
326
//  since they are designed to be used within JasPer only.
 
327
 
 
328
static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
 
329
  int bufsize)
 
330
{
 
331
        /* If this function is being called, the buffer should not have been
 
332
          initialized yet. */
 
333
        assert(!stream->bufbase_);
 
334
 
 
335
        if (bufmode != JAS_STREAM_UNBUF) {
 
336
                /* The full- or line-buffered mode is being employed. */
 
337
                if (!buf) {
 
338
                        /* The caller has not specified a buffer to employ, so allocate
 
339
                          one. */
 
340
                        if ((stream->bufbase_ = jas_malloc(JAS_STREAM_BUFSIZE +
 
341
                          JAS_STREAM_MAXPUTBACK))) {
 
342
                                stream->bufmode_ |= JAS_STREAM_FREEBUF;
 
343
                                stream->bufsize_ = JAS_STREAM_BUFSIZE;
 
344
                        } else {
 
345
                                /* The buffer allocation has failed.  Resort to unbuffered
 
346
                                  operation. */
 
347
                                stream->bufbase_ = stream->tinybuf_;
 
348
                                stream->bufsize_ = 1;
 
349
                        }
 
350
                } else {
 
351
                        /* The caller has specified a buffer to employ. */
 
352
                        /* The buffer must be large enough to accommodate maximum
 
353
                          putback. */
 
354
                        assert(bufsize > JAS_STREAM_MAXPUTBACK);
 
355
                        stream->bufbase_ = JAS_CAST(uchar *, buf);
 
356
                        stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK;
 
357
                }
 
358
        } else {
 
359
                /* The unbuffered mode is being employed. */
 
360
                /* A buffer should not have been supplied by the caller. */
 
361
                assert(!buf);
 
362
                /* Use a trivial one-character buffer. */
 
363
                stream->bufbase_ = stream->tinybuf_;
 
364
                stream->bufsize_ = 1;
 
365
        }
 
366
        stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK];
 
367
        stream->ptr_ = stream->bufstart_;
 
368
        stream->cnt_ = 0;
 
369
        stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;
 
370
}
 
371
 
 
372
static jas_stream_t *jas_stream_create()
 
373
{
 
374
        jas_stream_t *stream;
 
375
 
 
376
        if (!(stream = jas_malloc(sizeof(jas_stream_t)))) {
 
377
                return 0;
 
378
        }
 
379
        stream->openmode_ = 0;
 
380
        stream->bufmode_ = 0;
 
381
        stream->flags_ = 0;
 
382
        stream->bufbase_ = 0;
 
383
        stream->bufstart_ = 0;
 
384
        stream->bufsize_ = 0;
 
385
        stream->ptr_ = 0;
 
386
        stream->cnt_ = 0;
 
387
        stream->ops_ = 0;
 
388
        stream->obj_ = 0;
 
389
        stream->rwcnt_ = 0;
 
390
        stream->rwlimit_ = -1;
 
391
 
 
392
        return stream;
 
393
}
 
394
 
 
395
static void jas_stream_destroy(jas_stream_t *stream)
 
396
{
 
397
        /* If the memory for the buffer was allocated with malloc, free
 
398
        this memory. */
 
399
        if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
 
400
                jas_free(stream->bufbase_);
 
401
                stream->bufbase_ = 0;
 
402
        }
 
403
        jas_free(stream);
 
404
}
 
405
 
 
406
#endif//IL_NO_JP2