InteriorInstance::readLightmaps problem
by James Urquhart · in Torque Game Engine · 12/18/2004 (5:44 am) · 0 replies
There is a slight problem with the function, InteriorInstance::readLightmaps.
For reference, lets take a look at the first bit:
The first thing that is odd about this function is that it loads the Interior again, but of course, that is to extract the lightmaps from it (since they are actually cleared by the Interior Lightmap Manager).
However, there is a flaw with this method of extracting the lightmaps; It is using "mInteriorFilename" from the InteriorInstance as the filename for the interior. This could potentially be changed on the client prior to a relight, potentially allowing a person to "cheat" by purposefully swapping the filename for another equivalent interior (that also has the *same* number of lightmaps).
In order to exploit this potential problem, one needs to change the "interiorFile" property of an InteriorInstance to another interior filename, then relight the scene. However, i have not managed to successfully exploit it, as my changes to the "interiorFile" property seem to be being ignored.
Another possible way of exploiting this code would be to signal a third party program to swap around .dif files before one relights the mission. Since there appears to be no CRC checking in this code, there would not be much of a problem.
Since "readLightmaps" is only used in one place, "InteriorLMManager::loadBaseLightmaps", i thought it would be best to move the logic into there, eliminating the need to create a temporary array of bitmap pointers. I also changed it to load the interior stream via passing along the interior's resource object. (NOTE: this still has the potential problem of the previous point)
Replace everything in the function after "InstanceLMInfo * instanceInfo = interiorInfo->mInstances[instanceHandle];" with :
For reference, lets take a look at the first bit:
bool InteriorInstance::readLightmaps(GBitmap**** lightmaps)
{
...
// Load resource
Stream* pStream = ResourceManager->openStream(mInteriorFileName);
if (pStream == NULL) {
Con::errorf(ConsoleLogEntry::General, "Unable to load interior: %s", mInteriorFileName);
return false;
}
InteriorResource* pResource = new InteriorResource;
bool success = pResource->read(*pStream);
ResourceManager->closeStream(pStream);
...The first thing that is odd about this function is that it loads the Interior again, but of course, that is to extract the lightmaps from it (since they are actually cleared by the Interior Lightmap Manager).
However, there is a flaw with this method of extracting the lightmaps; It is using "mInteriorFilename" from the InteriorInstance as the filename for the interior. This could potentially be changed on the client prior to a relight, potentially allowing a person to "cheat" by purposefully swapping the filename for another equivalent interior (that also has the *same* number of lightmaps).
In order to exploit this potential problem, one needs to change the "interiorFile" property of an InteriorInstance to another interior filename, then relight the scene. However, i have not managed to successfully exploit it, as my changes to the "interiorFile" property seem to be being ignored.
Another possible way of exploiting this code would be to signal a third party program to swap around .dif files before one relights the mission. Since there appears to be no CRC checking in this code, there would not be much of a problem.
Since "readLightmaps" is only used in one place, "InteriorLMManager::loadBaseLightmaps", i thought it would be best to move the logic into there, eliminating the need to create a temporary array of bitmap pointers. I also changed it to load the interior stream via passing along the interior's resource object. (NOTE: this still has the potential problem of the previous point)
Replace everything in the function after "InstanceLMInfo * instanceInfo = interiorInfo->mInstances[instanceHandle];" with :
// Load interior via stream and extract lightmaps that way
Stream *str = ResourceManager->openStream(instanceInfo->mInstance->getResource()->mSourceResource);
InteriorResource *interiorRes = new InteriorResource();
interiorRes->read(*str);
ResourceManager->closeStream(str);
// Grab and seperate lightmaps from the interior's lightmaps vector
for(U32 i = 0; i < interiorRes->getNumDetailLevels(); i++)
{
Interior * interior = interiorRes->getDetailLevel(i);
Interior * lmInterior = instanceInfo->mInstance->getDetailLevel(i);
AssertFatal(interior && lmInterior, "InteriorLMManager::loadBaseLightmaps: invalid detail level in resource");
AssertFatal(lmInterior->getLMHandle() != LM_HANDLE(-1), "InteriorLMManager::loadBaseLightmaps: interior not added to manager");
AssertFatal(lmInterior->getLMHandle() < mInteriors.size(), "InteriorLMManager::loadBaseLightmaps: invalid interior");
InteriorLMInfo * interiorInfo = mInteriors[lmInterior->getLMHandle()];
InstanceLMInfo * baseInstanceInfo = interiorInfo->mInstances[0];
for(U32 j = 0; j < interiorInfo->mNumLightmaps; j++)
{
GBitmap *bmp = interior->mLightmaps[j];
if (baseInstanceInfo->mLightmapHandles[j])
{
TextureObject * texObj = *baseInstanceInfo->mLightmapHandles[j];
texObj->bitmap = bmp;
}
else
baseInstanceInfo->mLightmapHandles[j] = new TextureHandle(getTextureName(lmInterior, 0, j), bmp, BitmapNoDownloadTexture);
// Clear out references to this bitmap
interior->mLightmaps[j] = NULL;
}
interior->mLightmaps.clear();
}
delete interiorRes;
return(true);About the author