Commit message: 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.
CVE: CVE-2015-5203
CWE: CWE-190
Vulnerability description: Double free vulnerability in the jasper_image_stop_load function in JasPer 1.900.17 allows remote attackers to cause a denial of service (crash) via a crafted JPEG 2000 image file.

Project: jasper
File: jas_stream.c

int jas_stream_close(jas_stream_t *stream)
{
	/* Flush buffer if necessary. */
	jas_stream_flush(stream);

	/* Close the underlying stream object. */
	(*stream->ops_->close_)(stream->obj_);

	jas_stream_destroy(stream);

	return 0;
}

Project: jasper
File: jas_stream.c

static void jas_stream_destroy(jas_stream_t *stream)
{
	/* If the memory for the buffer was allocated with malloc, free
	this memory. */
	if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
		JAS_DBGLOG(100, ("jas_stream_destroy freeing buffer %p\n",
		  stream->bufbase_));
		jas_free(stream->bufbase_);
		stream->bufbase_ = 0;
	}
	jas_free(stream);
}

Project: jasper

 jas_stream_t *jas_stream_fopen(const char *filename, const char *mode)
 {
 	jas_stream_t *stream;
	jas_stream_fileobj_t *obj;
	int openflags;

	/* Allocate a stream object. */
	if (!(stream = jas_stream_create())) {
		return 0;
	}

	/* Parse the mode string. */
	stream->openmode_ = jas_strtoopenmode(mode);

	/* Determine the correct flags to use for opening the file. */
	if ((stream->openmode_ & JAS_STREAM_READ) &&
	  (stream->openmode_ & JAS_STREAM_WRITE)) {
		openflags = O_RDWR;
	} else if (stream->openmode_ & JAS_STREAM_READ) {
		openflags = O_RDONLY;
	} else if (stream->openmode_ & JAS_STREAM_WRITE) {
		openflags = O_WRONLY;
	} else {
		openflags = 0;
	}
	if (stream->openmode_ & JAS_STREAM_APPEND) {
		openflags |= O_APPEND;
	}
	if (stream->openmode_ & JAS_STREAM_BINARY) {
		openflags |= O_BINARY;
	}
	if (stream->openmode_ & JAS_STREAM_CREATE) {
		openflags |= O_CREAT | O_TRUNC;
	}

	/* Allocate space for the underlying file stream object. */
	if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) {
		jas_stream_destroy(stream);
		return 0;
	}
	obj->fd = -1;
	obj->flags = 0;
	obj->pathname[0] = '\0';
	stream->obj_ = (void *) obj;

	/* Select the operations for a file stream object. */
	stream->ops_ = &jas_stream_fileops;

	/* Open the underlying file. */
	if ((obj->fd = open(filename, openflags, JAS_STREAM_PERMS)) < 0) {
		jas_free(obj);
		jas_stream_destroy(stream);
		return 0;
	}

	/* By default, use full buffering for this type of stream. */
	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);

	return stream;
}

Project: jasper
File: jas_stream.c

jas_stream_t *jas_stream_freopen(const char *path, const char *mode, FILE *fp)
{
	jas_stream_t *stream;
	int openflags;

	/* Eliminate compiler warning about unused variable. */
	path = 0;

	/* Allocate a stream object. */
	if (!(stream = jas_stream_create())) {
		return 0;
	}

	/* Parse the mode string. */
	stream->openmode_ = jas_strtoopenmode(mode);

	/* Determine the correct flags to use for opening the file. */
	if ((stream->openmode_ & JAS_STREAM_READ) &&
	  (stream->openmode_ & JAS_STREAM_WRITE)) {
		openflags = O_RDWR;
	} else if (stream->openmode_ & JAS_STREAM_READ) {
		openflags = O_RDONLY;
	} else if (stream->openmode_ & JAS_STREAM_WRITE) {
		openflags = O_WRONLY;
	} else {
		openflags = 0;
	}
	if (stream->openmode_ & JAS_STREAM_APPEND) {
		openflags |= O_APPEND;
	}
	if (stream->openmode_ & JAS_STREAM_BINARY) {
		openflags |= O_BINARY;
	}
	if (stream->openmode_ & JAS_STREAM_CREATE) {
		openflags |= O_CREAT | O_TRUNC;
	}

	stream->obj_ = JAS_CAST(void *, fp);

	/* Select the operations for a file stream object. */
	stream->ops_ = &jas_stream_sfileops;

	/* By default, use full buffering for this type of stream. */
	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);

	return stream;
}

Project: jasper
File: jas_stream.c

char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize)
{
	int c;
	char *bufptr;
	assert(bufsize > 0);

	bufptr = buf;
	while (bufsize > 1) {
		if ((c = jas_stream_getc(stream)) == EOF) {
			break;
		}
		*bufptr++ = c;
		--bufsize;
		if (c == '\n') {
			break;
		}
	}
	*bufptr = '\0';
	return buf;
}

Project: jasper
File: jas_stream.c

 jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
 {
 	jas_stream_t *stream;
	jas_stream_memobj_t *obj;

	JAS_DBGLOG(100, ("jas_stream_memopen(%p, %d)\n", buf, bufsize));

	if (!(stream = jas_stream_create())) {
		return 0;
	}

	/* A stream associated with a memory buffer is always opened
	for both reading and writing in binary mode. */
	stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;

	/* Since the stream data is already resident in memory, buffering
	is not necessary. */
	/* But... It still may be faster to use buffering anyways. */
	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);

	/* Select the operations for a memory stream. */
	stream->ops_ = &jas_stream_memops;

	/* Allocate memory for the underlying memory stream object. */
	if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) {
		jas_stream_destroy(stream);
		return 0;
	}
	stream->obj_ = (void *) obj;

	/* Initialize a few important members of the memory stream object. */
	obj->myalloc_ = 0;
	obj->buf_ = 0;

	/* If the buffer size specified is nonpositive, then the buffer
	is allocated internally and automatically grown as needed. */
	if (bufsize <= 0) {
		obj->bufsize_ = 1024;
		obj->growable_ = 1;
	} else {
		obj->bufsize_ = bufsize;
		obj->growable_ = 0;
	}
	if (buf) {
		obj->buf_ = (unsigned char *) buf;
	} else {
		obj->buf_ = jas_malloc(obj->bufsize_);
		obj->myalloc_ = 1;
	}
	if (!obj->buf_) {
		jas_stream_close(stream);
		return 0;
	}
	JAS_DBGLOG(100, ("jas_stream_memopen buffer buf=%p myalloc=%d\n",
	  obj->buf_, obj->myalloc_));

	if (bufsize > 0 && buf) {
		/* If a buffer was supplied by the caller and its length is positive,
		  make the associated buffer data appear in the stream initially. */
		obj->len_ = bufsize;
	} else {
		/* The stream is initially empty. */
		obj->len_ = 0;
	}
	obj->pos_ = 0;
	
 	return stream;
 }

Project: jasper
File: jas_stream.c

int jas_stream_rewind(jas_stream_t *stream)
{
	return jas_stream_seek(stream, 0, SEEK_SET);
}

Project: jasper
File: jas_stream.c

long jas_stream_seek(jas_stream_t *stream, long offset, int origin)
{
	long newpos;

	/* The buffer cannot be in use for both reading and writing. */
	assert(!((stream->bufmode_ & JAS_STREAM_RDBUF) && (stream->bufmode_ &
	  JAS_STREAM_WRBUF)));

	/* Reset the EOF indicator (since we may not be at the EOF anymore). */
	stream->flags_ &= ~JAS_STREAM_EOF;

	if (stream->bufmode_ & JAS_STREAM_RDBUF) {
		if (origin == SEEK_CUR) {
			offset -= stream->cnt_;
		}
	} else if (stream->bufmode_ & JAS_STREAM_WRBUF) {
		if (jas_stream_flush(stream)) {
			return -1;
		}
	}
	stream->cnt_ = 0;
	stream->ptr_ = stream->bufstart_;
	stream->bufmode_ &= ~(JAS_STREAM_RDBUF | JAS_STREAM_WRBUF);

	if ((newpos = (*stream->ops_->seek_)(stream->obj_, offset, origin))
	  < 0) {
		return -1;
	}

	return newpos;
}

Project: jasper
File: jas_stream.c

long jas_stream_tell(jas_stream_t *stream)
{
	int adjust;
	int offset;

	if (stream->bufmode_ & JAS_STREAM_RDBUF) {
		adjust = -stream->cnt_;
	} else if (stream->bufmode_ & JAS_STREAM_WRBUF) {
		adjust = stream->ptr_ - stream->bufstart_;
	} else {
		adjust = 0;
	}

	if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR)) < 0) {
		return -1;
	}

	return offset + adjust;
}