Skip to content

Commit 634ce8e

Browse files
committed
Made some changes to the I/O stream library for memory streams.
There were a number of potential problems due to the possibility of integer overflow. Changed some integral types to the larger types size_t or ssize_t. For example, the function mem_resize now takes the buffer size parameter as a size_t. Added a new function jas_stream_memopen2, which takes a buffer size specified as a size_t instead of an int. This can be used in jas_image_cmpt_create to avoid potential overflow problems. Added a new function jas_deprecated to warn about reliance on deprecated library behavior.
1 parent e8f491b commit 634ce8e

File tree

5 files changed

+198
-15
lines changed

5 files changed

+198
-15
lines changed

src/libjasper/base/jas_debug.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,22 @@ int jas_memdump(FILE *out, void *data, size_t len)
135135
}
136136
return 0;
137137
}
138+
139+
/******************************************************************************\
140+
* Code.
141+
\******************************************************************************/
142+
143+
void jas_deprecated(const char *s)
144+
{
145+
static char message[] =
146+
"WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!\n"
147+
"WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!\n"
148+
"WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!\n"
149+
"YOUR CODE IS RELYING ON DEPRECATED FUNCTIONALTIY IN THE JASPER LIBRARY.\n"
150+
"THIS FUNCTIONALITY WILL BE REMOVED IN THE NEAR FUTURE.\n"
151+
"PLEASE FIX THIS PROBLEM BEFORE YOUR CODE STOPS WORKING!\n"
152+
;
153+
jas_eprintf("%s", message);
154+
jas_eprintf("The specific problem is as follows:\n%s\n", s);
155+
//abort();
156+
}

src/libjasper/base/jas_image.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx,
347347
!jas_safe_size_mul(size, cmpt->cps_, &size)) {
348348
goto error;
349349
}
350-
cmpt->stream_ = (inmem) ? jas_stream_memopen(0, size) :
350+
cmpt->stream_ = (inmem) ? jas_stream_memopen2(0, size) :
351351
jas_stream_tmpfile();
352352
if (!cmpt->stream_) {
353353
goto error;

src/libjasper/base/jas_stream.c

Lines changed: 170 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ static jas_stream_t *jas_stream_create()
169169
return stream;
170170
}
171171

172+
#if 0
173+
174+
/* Obsolete code. */
175+
172176
jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
173177
{
174178
jas_stream_t *stream;
@@ -238,6 +242,136 @@ jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
238242
return stream;
239243
}
240244

245+
#else
246+
247+
/*
248+
This function will eventually replace jas_stream_memopen.
249+
If buf is 0 and bufsize > 0:
250+
a buffer is dynamically allocated with size bufsize and this buffer is
251+
not growable.
252+
If buf is 0 and bufsize is 0:
253+
a buffer is dynamically allocated whose size will automatically grow to
254+
accommodate the amount of data written.
255+
If buf is not 0:
256+
bufsize (which, in this case, is not currently allowed to be zero) is
257+
the size of the (nongrowable) buffer pointed to by buf.
258+
*/
259+
260+
jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize)
261+
{
262+
jas_stream_t *stream;
263+
jas_stream_memobj_t *obj;
264+
265+
JAS_DBGLOG(100, ("jas_stream_memopen2(%p, %zu)\n", buf, bufsize));
266+
267+
assert((buf && bufsize > 0) || (!buf));
268+
269+
if (!(stream = jas_stream_create())) {
270+
return 0;
271+
}
272+
273+
/* A stream associated with a memory buffer is always opened
274+
for both reading and writing in binary mode. */
275+
stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
276+
277+
/* Since the stream data is already resident in memory, buffering
278+
is not necessary. */
279+
/* But... It still may be faster to use buffering anyways. */
280+
jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
281+
282+
/* Select the operations for a memory stream. */
283+
stream->ops_ = &jas_stream_memops;
284+
285+
/* Allocate memory for the underlying memory stream object. */
286+
if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) {
287+
jas_stream_destroy(stream);
288+
return 0;
289+
}
290+
stream->obj_ = (void *) obj;
291+
292+
/* Initialize a few important members of the memory stream object. */
293+
obj->myalloc_ = 0;
294+
obj->buf_ = 0;
295+
296+
/* If the buffer size specified is nonpositive, then the buffer
297+
is allocated internally and automatically grown as needed. */
298+
if (!bufsize) {
299+
obj->bufsize_ = 1024;
300+
obj->growable_ = 1;
301+
} else {
302+
obj->bufsize_ = bufsize;
303+
obj->growable_ = 0;
304+
}
305+
if (buf) {
306+
obj->buf_ = JAS_CAST(unsigned char *, buf);
307+
} else {
308+
obj->buf_ = jas_malloc(obj->bufsize_);
309+
obj->myalloc_ = 1;
310+
}
311+
if (!obj->buf_) {
312+
jas_stream_close(stream);
313+
return 0;
314+
}
315+
JAS_DBGLOG(100, ("jas_stream_memopen2 buffer buf=%p myalloc=%d\n",
316+
obj->buf_, obj->myalloc_));
317+
318+
if (bufsize > 0 && buf) {
319+
/* If a buffer was supplied by the caller and its length is positive,
320+
make the associated buffer data appear in the stream initially. */
321+
obj->len_ = bufsize;
322+
} else {
323+
/* The stream is initially empty. */
324+
obj->len_ = 0;
325+
}
326+
obj->pos_ = 0;
327+
328+
return stream;
329+
}
330+
331+
/*
332+
NOTE:
333+
The version of the function jas_stream_memopen only exists for backwards
334+
compatibility.
335+
Eventually, it should be replaced by jas_stream_memopen2.
336+
In retrospect, it was a very poor choice to have specified the buffer
337+
size parameter (bufsize) to have type int. On some machines, int may only
338+
be a 16-bit integer. This precludes larger-sized buffer allocations, which
339+
are needed in practice.
340+
341+
If bufsize <= 0, the buffer is growable; otherwise, the buffer has a fixed
342+
size of bufsize.
343+
If buf is 0, the buffer is dynamically allocated with jas_malloc.
344+
If buf is not 0 and bufsize <= 0 (which is not permitted in any
345+
circumstances), bad things will happen (especially if the buf was not
346+
allocated with jas_malloc).
347+
*/
348+
jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
349+
{
350+
char *new_buf;
351+
size_t new_bufsize;
352+
353+
JAS_DBGLOG(100, ("jas_stream_memopen(%p, %d)\n", buf, bufsize));
354+
if (bufsize < 0) {
355+
jas_deprecated("negative buffer size for jas_stream_memopen");
356+
}
357+
if (buf && bufsize <= 0) {
358+
// This was never a valid thing to do with the old API.
359+
jas_eprintf("Invalid use of jas_stream_memopen detected.\n");
360+
jas_deprecated("A user-provided buffer for "
361+
"jas_stream_memopen cannot be growable.\n");
362+
}
363+
if (bufsize <= 0) {
364+
new_bufsize = 0;
365+
new_buf = 0;
366+
} else {
367+
new_bufsize = bufsize;
368+
new_buf = buf;
369+
}
370+
return jas_stream_memopen2(new_buf, new_bufsize);
371+
}
372+
373+
#endif
374+
241375
jas_stream_t *jas_stream_fopen(const char *filename, const char *mode)
242376
{
243377
jas_stream_t *stream;
@@ -520,6 +654,10 @@ int jas_stream_read(jas_stream_t *stream, void *buf, int cnt)
520654
int c;
521655
char *bufptr;
522656

657+
if (cnt < 0) {
658+
jas_deprecated("negative count for jas_stream_read");
659+
}
660+
523661
bufptr = buf;
524662

525663
n = 0;
@@ -539,6 +677,10 @@ int jas_stream_write(jas_stream_t *stream, const void *buf, int cnt)
539677
int n;
540678
const char *bufptr;
541679

680+
if (cnt < 0) {
681+
jas_deprecated("negative count for jas_stream_write");
682+
}
683+
542684
bufptr = buf;
543685

544686
n = 0;
@@ -604,6 +746,9 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize)
604746
int jas_stream_gobble(jas_stream_t *stream, int n)
605747
{
606748
int m;
749+
if (n < 0) {
750+
jas_deprecated("negative count for jas_stream_gobble");
751+
}
607752
m = n;
608753
for (m = n; m > 0; --m) {
609754
if (jas_stream_getc(stream) == EOF) {
@@ -616,6 +761,9 @@ int jas_stream_gobble(jas_stream_t *stream, int n)
616761
int jas_stream_pad(jas_stream_t *stream, int n, int c)
617762
{
618763
int m;
764+
if (n < 0) {
765+
jas_deprecated("negative count for jas_stream_pad");
766+
}
619767
m = n;
620768
for (m = n; m > 0; --m) {
621769
if (jas_stream_putc(stream, c) == EOF)
@@ -988,7 +1136,7 @@ long jas_stream_length(jas_stream_t *stream)
9881136

9891137
static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt)
9901138
{
991-
int n;
1139+
ssize_t n;
9921140
assert(cnt >= 0);
9931141
assert(buf);
9941142

@@ -1001,14 +1149,21 @@ static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt)
10011149
return cnt;
10021150
}
10031151

1004-
static int mem_resize(jas_stream_memobj_t *m, int bufsize)
1152+
static int mem_resize(jas_stream_memobj_t *m, size_t bufsize)
10051153
{
10061154
unsigned char *buf;
10071155

10081156
//assert(m->buf_);
1009-
assert(bufsize >= 0);
1157+
//assert(bufsize >= 0);
1158+
1159+
JAS_DBGLOG(100, ("mem_resize(%p, %zu)\n", m, bufsize));
1160+
if (!bufsize) {
1161+
jas_eprintf(
1162+
"mem_resize was not really designed to handle a buffer of size 0\n"
1163+
"This may not work.\n"
1164+
);
1165+
}
10101166

1011-
JAS_DBGLOG(100, ("mem_resize(%p, %d)\n", m, bufsize));
10121167
if (!(buf = jas_realloc2(m->buf_, bufsize, sizeof(unsigned char))) &&
10131168
bufsize) {
10141169
JAS_DBGLOG(100, ("mem_resize realloc failed\n"));
@@ -1022,11 +1177,11 @@ static int mem_resize(jas_stream_memobj_t *m, int bufsize)
10221177

10231178
static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt)
10241179
{
1025-
int n;
1180+
size_t n;
10261181
int ret;
10271182
jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1028-
long newbufsize;
1029-
long newpos;
1183+
size_t newbufsize;
1184+
size_t newpos;
10301185

10311186
assert(buf);
10321187
assert(cnt >= 0);
@@ -1036,13 +1191,15 @@ static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt)
10361191
if (newpos > m->bufsize_ && m->growable_) {
10371192
newbufsize = m->bufsize_;
10381193
while (newbufsize < newpos) {
1039-
newbufsize <<= 1;
1040-
assert(newbufsize >= 0);
1194+
//newbufsize <<= 1;
1195+
if (!jas_safe_size_mul(newbufsize, 2, &newbufsize)) {
1196+
JAS_DBGLOG(100, ("new buffer size would cause overflow\n"));
1197+
return -1;
1198+
}
10411199
}
1042-
JAS_DBGLOG(100, ("mem_write resizing from %d to %z\n", m->bufsize_,
1200+
JAS_DBGLOG(100, ("mem_write resizing from %d to %zu\n", m->bufsize_,
10431201
newbufsize));
1044-
JAS_DBGLOG(100, ("mem_write resizing from %d to %ul\n", m->bufsize_,
1045-
JAS_CAST(unsigned long, newbufsize)));
1202+
assert(newbufsize > 0);
10461203
if (mem_resize(m, newbufsize)) {
10471204
return -1;
10481205
}
@@ -1076,7 +1233,7 @@ static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt)
10761233
static long mem_seek(jas_stream_obj_t *obj, long offset, int origin)
10771234
{
10781235
jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1079-
long newpos;
1236+
size_t newpos;
10801237

10811238
JAS_DBGLOG(100, ("mem_seek(%p, %ld, %d)\n", obj, offset, origin));
10821239
switch (origin) {

src/libjasper/include/jasper/jas_debug.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ int jas_eprintf(const char *fmt, ...);
107107
/* Dump memory to a stream. */
108108
int jas_memdump(FILE *out, void *data, size_t len);
109109

110+
/* Warn about use of deprecated functionality. */
111+
void jas_deprecated(const char *s);
112+
110113
#ifdef __cplusplus
111114
}
112115
#endif

src/libjasper/include/jasper/jas_stream.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ typedef struct {
267267
uchar *buf_;
268268

269269
/* The allocated size of the buffer for holding file data. */
270-
int bufsize_;
270+
size_t bufsize_;
271271

272272
/* The length of the file. */
273273
int_fast32_t len_;
@@ -293,6 +293,10 @@ jas_stream_t *jas_stream_fopen(const char *filename, const char *mode);
293293
/* Open a memory buffer as a stream. */
294294
jas_stream_t *jas_stream_memopen(char *buf, int bufsize);
295295

296+
/* Do not use this function.
297+
It will eventually replace jas_stream_memopen. */
298+
jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize);
299+
296300
/* Open a file descriptor as a stream. */
297301
jas_stream_t *jas_stream_fdopen(int fd, const char *mode);
298302

0 commit comments

Comments
 (0)