glTexImage2D超出缓冲区界限(iOS)

时间:2016-06-06 18:59:17

标签: ios opengl-es buffer-overflow

在下面的简单代码中,我将1通道数据加载到纹理。我将glTexImage2D()GL_LUMINANCE(1通道格式)和GL_UNSIGNED_BYTE一起使用,因此每像素需要一个字节。我分配一个大小等于像素数(2 x 2)的缓冲区,它代表输入像素数据(对于我们的目的,像素的值无关紧要。)

在启用Address Sanitizer的情况下运行以下代码时,它会在调用glTexImage2D()时检测到堆缓冲区溢出,并说它尝试读取超出堆分配缓冲区的范围:

#import <OpenGLES/ES2/gl.h>

//...

EAGLContext* context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:context];

GLsizei width = 2, height = 2;
void *data = malloc(width * height); // contents don't matter for now
glTexImage2D(GL_TEXTURE_2D,
             0,
             GL_LUMINANCE,
             width,
             height,
             0,
             GL_LUMINANCE,
             GL_UNSIGNED_BYTE,
             data);

这是100%可重现的,并且在iOS模拟器和设备上都会发生。只有将缓冲区的大小增加到6才会溢出(比预期的4大小大2)。

1x1和4x4的尺寸似乎没有这个问题,但是2x2和3x3都有。这似乎有点武断。

有什么问题?

1 个答案:

答案 0 :(得分:0)

由于@ genpfault的评论,我已经解决了这个问题。

我需要将解包对齐设置为1:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

具体来说,解包对齐确定每行开始的对齐方式。默认值为4.由于我的行没有任何特殊对齐,并且行字节之间没有间隙,因此对齐应为1.

第一行将始终对齐,因为malloc分配16对齐的缓冲区。但是第二行和后续行未对齐,默认对齐为4,除非行长度是4的倍数(这解释了为什么2x2和3x3不起作用,但4x4不起作用)。 1x1碰巧工作,因为它没有第二行。