[Openal-devel] Something dangerous-looking in linux impl.

Adam D. Moss adam at gimp.org
Tue Feb 10 11:36:07 PST 2004


Code below excerpted from al_buffer.c.

This looks like it might be potentially hazardous in a gnarly way.
Watch the use of buf->queue_list.items: in the first instance
it's being used as the 'next free position' cursor, but in
the second instance it's being used like a refcount.
_alBufferRemoveQueueRef() is written as though the sid to be
removed could occur anywhere in the queue_list, BUT
_alBufferAddQueueRef() will then possibly overwrite a
still-valid list entry if that previously removed entry
wasn't the very last sid in the list (the free-position cursor
has been moved one slot down from the end of the list, but
that doesn't necessarily correspond to the newly-vacated
slot).

As a second observation, since the realloc'd list in
_alBufferAddQueueRef() grows geometrically it will, after the
initial grow, be left with heap-noise in its final slots.  This
might potentially allow false-positive matches in
_alBufferRemoveQueueRef() and over-decrement the refcount.

I think that this can all only be of relevance when a buffer is
queued multiple times and/or on multiple sources.  (n.b. so is
unlikely to be related to my own problem.)  An identical set
of gotchas applies to _alBuffer{Add,Remove}CurrentRef() also.


static void _alBufferAddQueueRef( AL_buffer *buf, ALuint sid ) {
	ALvoid *temp;
	ALuint newsize = buf->queue_list.size;

	if(buf->queue_list.size <= buf->queue_list.items) {
		/* resize */
		newsize *= 2;
		newsize += 1;
		temp = realloc(buf->queue_list.sids, newsize * sizeof *buf->queue_list.sids);
		if(temp == NULL) {
			/* well la-di-da */
			return;
		}

		buf->queue_list.sids = temp;
		buf->queue_list.size = newsize;
	}

	buf->queue_list.sids[buf->queue_list.items++] = sid;

	return;
}

[....]

/*
  * _alBufferRemoveQueueRef( AL_buffer *buf, ALuint sid )
  *
  * removes the first queue reference from the AL_buffer *buf that refers to
  * sid.
  *
  * assumes locked context, buffer
  */
static void _alBufferRemoveQueueRef( AL_buffer *buf, ALuint sid ) {
	ALuint i;

	for(i = 0; i < buf->queue_list.size; i++) {
		if(buf->queue_list.sids[i] == sid) {
			buf->queue_list.sids[i] = 0;
			buf->queue_list.items--;

			return;
		}
	}

	return;
}


-- 
Adam D. Moss   . ,,^^   adam at gimp.org   http://www.foxbox.org/   co:3
"At this point the rocket becomes engorged with astronauts."



More information about the Openal-devel mailing list