Commit cf47cfdd by Alexis Hetu Committed by Nicolas Capens

Guard against out of bounds accesses caused by a large base level

A texture's base level can be any positive integer, but SwiftShader stores texture levels in a array that has an implementation dependent size (IMPLEMENTATION_MAX_TEXTURE_LEVELS). To avoid accessing this array out of bounds, a class was added to make sure all accesses to the array are done within its bounds. Change-Id: I9b439018f209a47371bd2959ba847345326964dd Reviewed-on: https://swiftshader-review.googlesource.com/20488Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 3655209d
...@@ -420,11 +420,6 @@ bool Texture::isMipmapFiltered(Sampler *sampler) const ...@@ -420,11 +420,6 @@ bool Texture::isMipmapFiltered(Sampler *sampler) const
Texture2D::Texture2D(GLuint name) : Texture(name) Texture2D::Texture2D(GLuint name) : Texture(name)
{ {
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
image[i] = nullptr;
}
mSurface = nullptr; mSurface = nullptr;
mColorbufferProxy = nullptr; mColorbufferProxy = nullptr;
...@@ -433,14 +428,7 @@ Texture2D::Texture2D(GLuint name) : Texture(name) ...@@ -433,14 +428,7 @@ Texture2D::Texture2D(GLuint name) : Texture(name)
Texture2D::~Texture2D() Texture2D::~Texture2D()
{ {
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) image.unbind(this);
{
if(image[i])
{
image[i]->unbind(this);
image[i] = nullptr;
}
}
if(mSurface) if(mSurface)
{ {
...@@ -562,14 +550,7 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLint inter ...@@ -562,14 +550,7 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLint inter
void Texture2D::bindTexImage(gl::Surface *surface) void Texture2D::bindTexImage(gl::Surface *surface)
{ {
for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) image.release();
{
if(image[level])
{
image[level]->release();
image[level] = nullptr;
}
}
image[0] = surface->getRenderTarget(); image[0] = surface->getRenderTarget();
...@@ -579,14 +560,7 @@ void Texture2D::bindTexImage(gl::Surface *surface) ...@@ -579,14 +560,7 @@ void Texture2D::bindTexImage(gl::Surface *surface)
void Texture2D::releaseTexImage() void Texture2D::releaseTexImage()
{ {
for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) image.release();
{
if(image[level])
{
image[level]->release();
image[level] = nullptr;
}
}
if(mSurface) if(mSurface)
{ {
...@@ -904,14 +878,6 @@ TextureCubeMap::TextureCubeMap(GLuint name) : Texture(name) ...@@ -904,14 +878,6 @@ TextureCubeMap::TextureCubeMap(GLuint name) : Texture(name)
{ {
for(int f = 0; f < 6; f++) for(int f = 0; f < 6; f++)
{ {
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
image[f][i] = nullptr;
}
}
for(int f = 0; f < 6; f++)
{
mFaceProxies[f] = nullptr; mFaceProxies[f] = nullptr;
mFaceProxyRefs[f] = 0; mFaceProxyRefs[f] = 0;
} }
...@@ -919,20 +885,9 @@ TextureCubeMap::TextureCubeMap(GLuint name) : Texture(name) ...@@ -919,20 +885,9 @@ TextureCubeMap::TextureCubeMap(GLuint name) : Texture(name)
TextureCubeMap::~TextureCubeMap() TextureCubeMap::~TextureCubeMap()
{ {
for(int f = 0; f < 6; f++)
{
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
if(image[f][i])
{
image[f][i]->unbind(this);
image[f][i] = nullptr;
}
}
}
for(int i = 0; i < 6; i++) for(int i = 0; i < 6; i++)
{ {
image[i].unbind(this);
mFaceProxies[i] = nullptr; mFaceProxies[i] = nullptr;
} }
} }
...@@ -1440,11 +1395,6 @@ bool TextureCubeMap::isShared(GLenum target, unsigned int level) const ...@@ -1440,11 +1395,6 @@ bool TextureCubeMap::isShared(GLenum target, unsigned int level) const
Texture3D::Texture3D(GLuint name) : Texture(name) Texture3D::Texture3D(GLuint name) : Texture(name)
{ {
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
image[i] = nullptr;
}
mSurface = nullptr; mSurface = nullptr;
mColorbufferProxy = nullptr; mColorbufferProxy = nullptr;
...@@ -1453,14 +1403,7 @@ Texture3D::Texture3D(GLuint name) : Texture(name) ...@@ -1453,14 +1403,7 @@ Texture3D::Texture3D(GLuint name) : Texture(name)
Texture3D::~Texture3D() Texture3D::~Texture3D()
{ {
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) image.unbind(this);
{
if(image[i])
{
image[i]->unbind(this);
image[i] = nullptr;
}
}
if(mSurface) if(mSurface)
{ {
......
...@@ -45,6 +45,54 @@ enum ...@@ -45,6 +45,54 @@ enum
IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = sw::OUTLINE_RESOLUTION, IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = sw::OUTLINE_RESOLUTION,
}; };
class ImageLevels
{
public:
inline const egl::Image* operator[](size_t index) const
{
return (index < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? image[index] : nullptr;
}
inline egl::Image*& operator[](size_t index)
{
if(index < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
{
return image[index];
}
static egl::Image* nullImage;
nullImage = nullptr;
return nullImage;
}
inline void release()
{
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
if(image[i])
{
image[i]->release();
image[i] = nullptr;
}
}
}
inline void unbind(const egl::Texture* texture)
{
for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
if(image[i])
{
image[i]->unbind(texture);
image[i] = nullptr;
}
}
}
private:
egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS] = {};
};
class Texture : public egl::Texture class Texture : public egl::Texture
{ {
public: public:
...@@ -192,7 +240,7 @@ protected: ...@@ -192,7 +240,7 @@ protected:
bool isMipmapComplete() const; bool isMipmapComplete() const;
egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ImageLevels image;
gl::Surface *mSurface; gl::Surface *mSurface;
...@@ -265,7 +313,7 @@ private: ...@@ -265,7 +313,7 @@ private:
// face is one of the GL_TEXTURE_CUBE_MAP_* enumerants. Returns nullptr on failure. // face is one of the GL_TEXTURE_CUBE_MAP_* enumerants. Returns nullptr on failure.
egl::Image *getImage(GLenum face, unsigned int level); egl::Image *getImage(GLenum face, unsigned int level);
egl::Image *image[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ImageLevels image[6];
// A specific internal reference count is kept for colorbuffer proxy references, // A specific internal reference count is kept for colorbuffer proxy references,
// because, as the renderbuffer acting as proxy will maintain a binding pointer // because, as the renderbuffer acting as proxy will maintain a binding pointer
...@@ -321,7 +369,7 @@ protected: ...@@ -321,7 +369,7 @@ protected:
bool isMipmapComplete() const; bool isMipmapComplete() const;
egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ImageLevels image;
gl::Surface *mSurface; gl::Surface *mSurface;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment