OSDN Git Service

Guard against out of bounds accesses caused by a large base level
authorAlexis Hetu <sugoi@google.com>
Tue, 4 Sep 2018 15:30:22 +0000 (11:30 -0400)
committerNicolas Capens <nicolascapens@google.com>
Fri, 7 Sep 2018 21:44:33 +0000 (21:44 +0000)
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/20488
Tested-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
src/OpenGL/libGLESv2/Texture.cpp
src/OpenGL/libGLESv2/Texture.h

index 4e63750..0cf4084 100644 (file)
@@ -420,11 +420,6 @@ bool Texture::isMipmapFiltered(Sampler *sampler) const
 
 Texture2D::Texture2D(GLuint name) : Texture(name)
 {
-       for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-       {
-               image[i] = nullptr;
-       }
-
        mSurface = nullptr;
 
        mColorbufferProxy = nullptr;
@@ -433,14 +428,7 @@ Texture2D::Texture2D(GLuint name) : Texture(name)
 
 Texture2D::~Texture2D()
 {
-       for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-       {
-               if(image[i])
-               {
-                       image[i]->unbind(this);
-                       image[i] = nullptr;
-               }
-       }
+       image.unbind(this);
 
        if(mSurface)
        {
@@ -562,14 +550,7 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLint inter
 
 void Texture2D::bindTexImage(gl::Surface *surface)
 {
-       for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
-       {
-               if(image[level])
-               {
-                       image[level]->release();
-                       image[level] = nullptr;
-               }
-       }
+       image.release();
 
        image[0] = surface->getRenderTarget();
 
@@ -579,14 +560,7 @@ void Texture2D::bindTexImage(gl::Surface *surface)
 
 void Texture2D::releaseTexImage()
 {
-       for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
-       {
-               if(image[level])
-               {
-                       image[level]->release();
-                       image[level] = nullptr;
-               }
-       }
+       image.release();
 
        if(mSurface)
        {
@@ -904,14 +878,6 @@ TextureCubeMap::TextureCubeMap(GLuint name) : Texture(name)
 {
        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;
                mFaceProxyRefs[f] = 0;
        }
@@ -919,20 +885,9 @@ TextureCubeMap::TextureCubeMap(GLuint name) : Texture(name)
 
 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++)
        {
+               image[i].unbind(this);
                mFaceProxies[i] = nullptr;
        }
 }
@@ -1440,11 +1395,6 @@ bool TextureCubeMap::isShared(GLenum target, unsigned int level) const
 
 Texture3D::Texture3D(GLuint name) : Texture(name)
 {
-       for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-       {
-               image[i] = nullptr;
-       }
-
        mSurface = nullptr;
 
        mColorbufferProxy = nullptr;
@@ -1453,14 +1403,7 @@ Texture3D::Texture3D(GLuint name) : Texture(name)
 
 Texture3D::~Texture3D()
 {
-       for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-       {
-               if(image[i])
-               {
-                       image[i]->unbind(this);
-                       image[i] = nullptr;
-               }
-       }
+       image.unbind(this);
 
        if(mSurface)
        {
index 017acab..4f57d32 100644 (file)
@@ -45,6 +45,54 @@ enum
        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
 {
 public:
@@ -192,7 +240,7 @@ protected:
 
        bool isMipmapComplete() const;
 
-       egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+       ImageLevels image;
 
        gl::Surface *mSurface;
 
@@ -265,7 +313,7 @@ private:
        // face is one of the GL_TEXTURE_CUBE_MAP_* enumerants. Returns nullptr on failure.
        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,
        // because, as the renderbuffer acting as proxy will maintain a binding pointer
@@ -321,7 +369,7 @@ protected:
 
        bool isMipmapComplete() const;
 
-       egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+       ImageLevels image;
 
        gl::Surface *mSurface;