Exemple #1
0
S32 lsa_postadd_lists(U8 *buffer, S32 offset1, LLScriptLibData *data, S32 heapsize)
{
	if (get_register(buffer, LREG_FR))
		return 0;
	LLScriptLibData *list1 = lsa_get_data(buffer, offset1, TRUE);

	if (!list1)
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete list1;
		return 0;
	}

	if (list1->mType != LST_LIST)
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete list1;
		return 0;
	}

	LLScriptLibData *runner = list1;

	while (runner->mListp)
	{
		runner = runner->mListp;
	}

	runner->mListp = data->mListp;

	return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
}
Exemple #2
0
S32 lsa_cmp_strings(U8 *buffer, S32 offset1, S32 offset2)
{
	if (get_register(buffer, LREG_FR))
		return 0;
	LLScriptLibData *string1;
	LLScriptLibData *string2;

	string1 = lsa_get_data(buffer, offset1, TRUE);
	string2 = lsa_get_data(buffer, offset2, TRUE);
	
	if (  (!string1)
		||(!string2))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete string1;
		delete string2;
		return 0;
	}

	char *test1 = NULL, *test2 = NULL;

	if (string1->mType == LST_STRING)
	{
		test1 = string1->mString;
	}
	else if (string1->mType == LST_KEY)
	{
		test1 = string1->mKey;
	}
	if (string2->mType == LST_STRING)
	{
		test2 = string2->mString;
	}
	else if (string2->mType == LST_KEY)
	{
		test2 = string2->mKey;
	}

	if (  (!test1)
		||(!test2))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete string1;
		delete string2;
		return 0;
	}
	S32 retval = strcmp(test1, test2);

	delete string1;
	delete string2;

	return retval;
}
Exemple #3
0
S32 lsa_cat_lists(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
{
	if (get_register(buffer, LREG_FR))
		return 0;
	LLScriptLibData *list1;
	LLScriptLibData *list2;
	if (offset1 != offset2)
	{
		list1 = lsa_get_data(buffer, offset1, TRUE);
		list2 = lsa_get_data(buffer, offset2, TRUE);
	}
	else
	{
		list1 = lsa_get_data(buffer, offset1, TRUE);
		list2 = lsa_get_data(buffer, offset2, TRUE);
	}

	if (  (!list1)
		||(!list2))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete list1;
		delete list2;
		return 0;
	}

	if (  (list1->mType != LST_LIST)
		||(list2->mType != LST_LIST))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete list1;
		delete list2;
		return 0;
	}

	LLScriptLibData *runner = list1;

	while (runner->mListp)
	{
		runner = runner->mListp;
	}

	runner->mListp = list2->mListp;

	list2->mListp = NULL;

	delete list2;

	return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
}
Exemple #4
0
LLScriptLibData *lsa_get_list_ptr(U8 *buffer, S32 &offset, BOOL b_dec_ref)
{
	if (get_register(buffer, LREG_FR))
		return (new LLScriptLibData);
	S32 orig_offset = offset;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
	offset += get_register(buffer, LREG_HR) - 1;
	if (  (offset < get_register(buffer, LREG_HR))
		||(offset >= get_register(buffer, LREG_HP)))
	{
		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
		return (new LLScriptLibData);
	}
	LLScriptAllocEntry entry;
	bytestream2alloc_entry(entry, buffer, offset);

	if (!entry.mType)
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		return NULL;
	}

	LLScriptLibData base, *tip = &base;

	if (entry.mType != LST_LIST)
	{
		return NULL;
	}
	else
	{
		// get length of list
		S32 i, length = bytestream2integer(buffer, offset);

		for (i = 0; i < length; i++)
		{
			S32 address = bytestream2integer(buffer, offset);
			tip->mListp = lsa_get_data(buffer, address, FALSE);
			tip = tip->mListp;
		}
	}
	if (b_dec_ref)
	{
		lsa_decrease_ref_count(buffer, orig_offset);
	}
	tip = base.mListp;
	base.mListp = NULL;
	return tip;
}
void LLScriptHeapRunTime::increaseRefCount(S32 address)
{
	if (!mBuffer)
		return;

	if (!address)
	{
		// unused temp string entry
		return;
	}

	// get current reference count
	S32 toffset = address + 4;
	S32 count = bytestream2integer(mBuffer, toffset);

	count++;

	if (mbPrint)
		printf("0x%X inc ref count %d\n", address - mHeapRegister, count);

	// see which type it is
	U8 type = *(mBuffer + toffset);

	if (type == LSCRIPTTypeByte[LST_STRING])
	{
		toffset = address + 4;
		integer2bytestream(mBuffer, toffset, count);
	}
	// TO DO: put list stuff here!
	else
	{
		set_fault(mBuffer, LSRF_HEAP_ERROR);
	}
}
S32 LLScriptHeapRunTime::addData(char *string)
{
	if (!mBuffer)
		return 0;

	S32 size = strlen(string) + 1;
	S32 block_offset = findOpenBlock(size + HEAP_BLOCK_HEADER_SIZE);

	if (mCurrentPosition)
	{
		S32 offset = mCurrentPosition;
		if (offset + block_offset + HEAP_BLOCK_HEADER_SIZE + LSCRIPTDataSize[LST_INTEGER] >= mStackPointer)
		{
			set_fault(mBuffer, LSRF_STACK_HEAP_COLLISION);
			return 0;
		}
		// cool, we've found a spot!
		// set offset
		integer2bytestream(mBuffer, offset, block_offset);
		// set reference count
		integer2bytestream(mBuffer, offset, 1);
		// set type
		*(mBuffer + offset++) = LSCRIPTTypeByte[LST_STRING];
		// plug in data
		char2bytestream(mBuffer, offset, string);
		if (mbPrint)
			printf("0x%X created ref count %d\n", mCurrentPosition - mHeapRegister, 1);

		// now, zero out next offset to prevent "trouble"
	//	offset = mCurrentPosition + size + HEAP_BLOCK_HEADER_SIZE;
	//	integer2bytestream(mBuffer, offset, 0);
	}
	return mCurrentPosition;
}
Exemple #7
0
S32 lsa_cmp_lists(U8 *buffer, S32 offset1, S32 offset2)
{
	if (get_register(buffer, LREG_FR))
		return 0;
	LLScriptLibData *list1;
	LLScriptLibData *list2;
	if (offset1 != offset2)
	{
		list1 = lsa_get_data(buffer, offset1, TRUE);
		list2 = lsa_get_data(buffer, offset2, TRUE);
	}
	else
	{
		list1 = lsa_get_data(buffer, offset1, FALSE);
		list2 = lsa_get_data(buffer, offset2, TRUE);
	}

	if (  (!list1)
		||(!list2))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete list1;
		delete list2;
		return 0;
	}

	if (  (list1->mType != LST_LIST)
		||(list2->mType != LST_LIST))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete list1;
		delete list2;
		return 0;
	}

	S32 length1 = list1->getListLength();
	S32 length2 = list2->getListLength();
	delete list1;
	delete list2;
	return length1 - length2;
}
Exemple #8
0
void lsa_decrease_ref_count(U8 *buffer, S32 offset)
{
	if (get_register(buffer, LREG_FR))
		return;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
	offset += get_register(buffer, LREG_HR) - 1;
	if (  (offset < get_register(buffer, LREG_HR))
		||(offset >= get_register(buffer, LREG_HP)))
	{
		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
		return;
	}
	S32 orig_offset = offset;
	LLScriptAllocEntry entry;
	bytestream2alloc_entry(entry, buffer, offset);

	entry.mReferenceCount--;

	if (entry.mReferenceCount < 0)
	{
		entry.mReferenceCount = 0;
		set_fault(buffer, LSRF_HEAP_ERROR);
	}
	else if (!entry.mReferenceCount)
	{
		if (entry.mType == LST_LIST)
		{
			S32 i, num = bytestream2integer(buffer, offset);
			for (i = 0; i < num; i++)
			{
				S32 list_offset = bytestream2integer(buffer, offset);
				lsa_decrease_ref_count(buffer, list_offset);
			}
		}
		entry.mType = LST_NULL;
	}

	alloc_entry2bytestream(buffer, orig_offset, entry);
}
void LLScriptHeapRunTime::decreaseRefCount(S32 address)
{
	if (!mBuffer)
		return;

	if (!address)
	{
		// unused temp string entry
		return;
	}

	// get offset
	S32 toffset = address;
	// read past offset (rely on function side effect)
	bytestream2integer(mBuffer, toffset);

	// get current reference count
	S32 count = bytestream2integer(mBuffer, toffset);

	// see which type it is
	U8 type = *(mBuffer + toffset);

	if (type == LSCRIPTTypeByte[LST_STRING])
	{
		count--;

		if (mbPrint)
			printf("0x%X dec ref count %d\n", address - mHeapRegister, count);

		toffset = address + 4;
		integer2bytestream(mBuffer, toffset, count);
		if (!count)
		{
			// we can blow this one away
			removeData(address);
		}
	}
	// TO DO: put list stuff here!
	else
	{
		set_fault(mBuffer, LSRF_HEAP_ERROR);
	}
}
Exemple #10
0
void lsa_increase_ref_count(U8 *buffer, S32 offset)
{
	if (get_register(buffer, LREG_FR))
		return;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
	offset += get_register(buffer, LREG_HR) - 1;
	if (  (offset < get_register(buffer, LREG_HR))
		||(offset >= get_register(buffer, LREG_HP)))
	{
		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
		return;
	}
	S32 orig_offset = offset;
	LLScriptAllocEntry entry;
	bytestream2alloc_entry(entry, buffer, offset);

	entry.mReferenceCount++;

	alloc_entry2bytestream(buffer, orig_offset, entry);
}
Exemple #11
0
S32 lsa_cat_strings(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
{
	if (get_register(buffer, LREG_FR))
		return 0;
	LLScriptLibData *string1;
	LLScriptLibData *string2;
	if (offset1 != offset2)
	{
		string1 = lsa_get_data(buffer, offset1, TRUE);
		string2 = lsa_get_data(buffer, offset2, TRUE);
	}
	else
	{
		string1 = lsa_get_data(buffer, offset1, TRUE);
		string2 = lsa_get_data(buffer, offset2, TRUE);
	}

	if (  (!string1)
		||(!string2))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete string1;
		delete string2;
		return 0;
	}

	char *test1 = NULL, *test2 = NULL;

	if (string1->mType == LST_STRING)
	{
		test1 = string1->mString;
	}
	else if (string1->mType == LST_KEY)
	{
		test1 = string1->mKey;
	}
	if (string2->mType == LST_STRING)
	{
		test2 = string2->mString;
	}
	else if (string2->mType == LST_KEY)
	{
		test2 = string2->mKey;
	}

	if (  (!test1)
		||(!test2))
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		delete string1;
		delete string2;
		return 0;
	}

	S32 size = (S32)strlen(test1) + (S32)strlen(test2) + 1;			/*Flawfinder: ignore*/

	LLScriptLibData *string3 = new LLScriptLibData;
	string3->mType = LST_STRING;
	string3->mString = new char[size];
	strcpy(string3->mString, test1);			/*Flawfinder: ignore*/
	strcat(string3->mString, test2);			/*Flawfinder: ignore*/

	delete string1;
	delete string2;

	return lsa_heap_add_data(buffer, string3, heapsize, TRUE);
}
Exemple #12
0
LLScriptLibData *lsa_get_data(U8 *buffer, S32 &offset, BOOL b_dec_ref)
{
	if (get_register(buffer, LREG_FR))
		return (new LLScriptLibData);
	S32 orig_offset = offset;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
	offset += get_register(buffer, LREG_HR) - 1;
	if (  (offset < get_register(buffer, LREG_HR))
		||(offset >= get_register(buffer, LREG_HP)))
	{
		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
		return (new LLScriptLibData);
	}
	LLScriptAllocEntry entry;
	bytestream2alloc_entry(entry, buffer, offset);

	LLScriptLibData *retval = new LLScriptLibData;

	if (!entry.mType)
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		return retval;
	}

	retval->mType = (LSCRIPTType)entry.mType;
	if (entry.mType != LST_LIST)
	{
		switch(entry.mType)
		{
		case LST_INTEGER:
			retval->mInteger = bytestream2integer(buffer, offset);
			break;
		case LST_FLOATINGPOINT:
			retval->mFP = bytestream2float(buffer, offset);
			break;
		case LST_KEY:
			bytestream2char(gLSAStringRead, buffer, offset, sizeof(gLSAStringRead)); // global sring buffer? for real? :(
			retval->mKey = new char[strlen(gLSAStringRead) + 1];		/*Flawfinder: ignore*/
			strcpy(retval->mKey, gLSAStringRead);			/*Flawfinder: ignore*/
			break;
		case LST_STRING:
			bytestream2char(gLSAStringRead, buffer, offset, sizeof(gLSAStringRead));
			retval->mString = new char[strlen(gLSAStringRead) + 1];		/*Flawfinder: ignore*/
			strcpy(retval->mString, gLSAStringRead);			/*Flawfinder: ignore*/
			break;
		case LST_VECTOR:
			bytestream2vector(retval->mVec, buffer, offset);
			break;
		case LST_QUATERNION:
			bytestream2quaternion(retval->mQuat, buffer, offset);
			break;
		default:
			break;
		}
	}
	else
	{
		// get length of list
		S32 i, length = bytestream2integer(buffer, offset);
		LLScriptLibData *tip = retval;

		for (i = 0; i < length; i++)
		{
			S32 address = bytestream2integer(buffer, offset);
			tip->mListp = lsa_get_data(buffer, address, FALSE);
			tip = tip->mListp;
		}
	}
	if (retval->checkForMultipleLists())
	{
		set_fault(buffer, LSRF_NESTING_LISTS);
	}
	if (b_dec_ref)
	{
		lsa_decrease_ref_count(buffer, orig_offset);
	}
	return retval;
}
Exemple #13
0
S32 lsa_heap_add_data(U8 *buffer, LLScriptLibData *data, S32 heapsize, BOOL b_delete)
{
	if (get_register(buffer, LREG_FR))
		return 1;
	LLScriptAllocEntry entry, nextentry;
	S32 hr = get_register(buffer, LREG_HR);
	S32 hp = get_register(buffer, LREG_HP);
	S32 current_offset, next_offset, offset = hr;
	S32 size = 0;

	switch(data->mType)
	{
	case LST_INTEGER:
		size = 4;
		break;
	case LST_FLOATINGPOINT:
		size = 4;
		break;
	case LST_KEY:
	        // NOTE: babbage: defensive as some library calls set data to NULL
	        size = data->mKey ? (S32)strlen(data->mKey) + 1 : 1; /*Flawfinder: ignore*/
		break;
	case LST_STRING:
                // NOTE: babbage: defensive as some library calls set data to NULL
            	size = data->mString ? (S32)strlen(data->mString) + 1 : 1; /*Flawfinder: ignore*/
		break;
	case LST_LIST:
		//	list data		4 bytes of number of entries followed by number of pointer
		size = 4 + 4*data->getListLength();
		if (data->checkForMultipleLists())
		{
			set_fault(buffer, LSRF_NESTING_LISTS);
		}
		break;
	case LST_VECTOR:
		size = 12;
		break;
	case LST_QUATERNION:
		size = 16;
		break;
	default:
		break;
	}

	current_offset = offset;
	bytestream2alloc_entry(entry, buffer, offset);

	do
	{
		hp = get_register(buffer, LREG_HP);
		if (!entry.mType)
		{
			if (entry.mSize >= size + SIZEOF_SCRIPT_ALLOC_ENTRY + 4)
			{
				offset = current_offset;
				lsa_split_block(buffer, offset, size, entry);
				entry.mType = data->mType;
				entry.mSize = size;
				entry.mReferenceCount = 1;
				offset = current_offset;
				alloc_entry2bytestream(buffer, offset, entry);
				lsa_insert_data(buffer, offset, data, entry, heapsize);
				hp = get_register(buffer, LREG_HP);
				S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
				if (new_hp >= hr + heapsize)
				{
					break;
				}
				if (new_hp > hp)
				{
					set_register(buffer, LREG_HP, new_hp);
					hp = get_register(buffer, LREG_HP);
				}
				if (b_delete)
					delete data;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
				if (current_offset <= hp)
					return current_offset - hr + 1;
				else
					return hp - hr + 1;
			}
			else if (entry.mSize >= size)
			{
				entry.mType = data->mType;
				entry.mReferenceCount = 1;
				offset = current_offset;
				alloc_entry2bytestream(buffer, offset, entry);
				lsa_insert_data(buffer, offset, data, entry, heapsize);
				hp = get_register(buffer, LREG_HP);
				if (b_delete)
					delete data;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
				return current_offset - hr + 1;
			}
		}
		offset += entry.mSize;
		if (offset < hr + heapsize)
		{
			next_offset = offset;
			bytestream2alloc_entry(nextentry, buffer, offset);
			if (!nextentry.mType && !entry.mType)
			{
				entry.mSize += nextentry.mSize + SIZEOF_SCRIPT_ALLOC_ENTRY;
				offset = current_offset;
				alloc_entry2bytestream(buffer, offset, entry);
			}
			else
			{
				current_offset = next_offset;
				entry = nextentry;
			}

			// this works whether we are bumping out or coming in
			S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;

			// make sure we aren't about to be stupid
			if (new_hp >= hr + heapsize)
			{
				break;
			}
			if (new_hp > hp)
			{
				set_register(buffer, LREG_HP, new_hp);
				hp = get_register(buffer, LREG_HP);
			}
		}
		else
		{
			break;
		}
	} while (1);
	set_fault(buffer, LSRF_STACK_HEAP_COLLISION);
	reset_hp_to_safe_spot(buffer);
	if (b_delete)
		delete data;
	return 0;
}
S32 LLScriptHeapRunTime::findOpenBlock(S32 size)
{
	S32 offset;
	S32 toffset;
	U8 blocktype;

	while(1)
	{
		if (mCurrentPosition + size >= mStackPointer)
		{
			set_fault(mBuffer, LSRF_STACK_HEAP_COLLISION);
			mCurrentPosition = 0;
		}

		toffset = mCurrentPosition;
		offset = bytestream2integer(mBuffer, toffset);
		if (!offset)
		{
			// we've reached the end of Heap, return this location if we'll fit
			// do we need to coalesce with last empty space?
			if (mLastEmpty)
			{
				// ok, that everything from mLastEmpty to us is empty, so we don't need a block
				// zero out the last empty's offset and return it
				mCurrentPosition = mLastEmpty;
				integer2bytestream(mBuffer, mLastEmpty, 0);
				mLastEmpty = 0;
			}
			// now, zero out next offset to prevent "trouble"
			offset = mCurrentPosition + size;
			integer2bytestream(mBuffer, offset, 0);

			// set HP to appropriate value
			set_register(mBuffer, LREG_HP, mCurrentPosition + size);
			return size;
		}

		// ok, is this slot empty?
		toffset += LSCRIPTDataSize[LST_INTEGER];

		blocktype = *(mBuffer + toffset++);

		if (!blocktype)
		{
			// Empty block, do we need to coalesce?
			if (mLastEmpty)
			{
				coalesce(mLastEmpty, mCurrentPosition);
				mCurrentPosition = mLastEmpty;
				toffset = mCurrentPosition;
				offset = bytestream2integer(mBuffer, toffset);
			}

			// do we fit in this block?
			if (offset >= size)
			{
				// do we need to split the block? (only split if splitting will leave > HEAP_BLOCK_SPLIT_THRESHOLD bytes of free space)
				if (offset - HEAP_BLOCK_SPLIT_THRESHOLD >= size)
				{
					split(mCurrentPosition, size);
					return size;
				}
				else
					return offset;
			}
		}
		// nothing found, keep looking
		mCurrentPosition += offset;
	}
	// fake return to prevent warnings
	mCurrentPosition = 0;
	return 0;
}