glsl-array-bounds: set out-of-bounds array index inside shader
[piglit.git] / tests / shaders / glsl-uniform-out-of-bounds.c
blobd3ae2f61bc31fa31da587c003615f10a55fb26d6
1 /*
2 * Copyright (c) 2009 Nicolai Hähnle
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
23 * Authors:
24 * Nicolai Hähnle <nhaehnle@gmail.com>
28 /**
29 * \file
30 * Test that out-of-bound writes to uniform locations are caught properly.
33 #include <limits.h>
34 #include <stdarg.h>
35 #include <stdio.h>
37 #include "piglit-util-gl.h"
39 PIGLIT_GL_TEST_CONFIG_BEGIN
41 config.supports_gl_compat_version = 10;
43 config.window_visual = PIGLIT_GL_VISUAL_RGB;
45 PIGLIT_GL_TEST_CONFIG_END
47 static void expect_error(GLenum expect, const char * where, ...)
49 GLenum error = glGetError();
50 if (error != expect) {
51 va_list va;
53 fprintf(stderr, "Expected OpenGL error 0x%04x, got 0x%04x\nat: ", expect, error);
55 va_start(va, where);
56 vfprintf(stderr, where, va);
57 va_end(va);
58 fprintf(stderr, "\n");
60 piglit_report_result(PIGLIT_FAIL);
64 static GLuint compile_shader(GLenum shaderType, const char * text)
66 GLuint shader;
67 GLint status;
69 shader = glCreateShaderObjectARB(shaderType);
70 glShaderSourceARB(shader, 1, (const GLchar **)&text, NULL);
71 glCompileShaderARB(shader);
73 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
74 if (!status) {
75 GLchar log[1000];
76 GLsizei len;
77 glGetInfoLogARB(shader, 1000, &len, log);
78 fprintf(stderr, "Error: problem compiling shader: %s\n", log);
79 piglit_report_result(PIGLIT_FAIL);
81 return shader;
84 static GLuint link_program(GLuint vs, GLuint fs)
86 GLuint program;
87 GLint status;
89 program = glCreateProgramObjectARB();
90 if (vs)
91 glAttachObjectARB(program, vs);
92 if (fs)
93 glAttachObjectARB(program, fs);
95 glLinkProgramARB(program);
96 glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &status);
97 if (!status) {
98 GLchar log[1000];
99 GLsizei len;
100 glGetInfoLogARB(program, 1000, &len, log);
101 fprintf(stderr, "Error: problem linking program: %s\n", log);
102 piglit_report_result(PIGLIT_FAIL);
105 return program;
108 static const GLfloat lots_of_zeros[16*1024] = { 0.0f, };
110 static const char vs_vector_template[] =
111 "uniform %s a;\n"
112 "uniform %s b[4];\n"
113 "uniform %s c[4];\n"
114 "varying %s v;\n"
115 "void main() {\n"
116 " v = a + b[3] + c[0] + c[1] + c[2] + c[3];\n"
117 " gl_Position = vec4(0,0,0,1);\n"
118 "}\n";
120 static const char fs_vector_template[] =
121 "varying %s v;\n"
122 "void main() {\n"
123 " gl_FragColor = vec4(v%s);\n"
124 "}\n";
127 static void test_vector(const char *glsl_type, const char * suffix,
128 void (GLAPIENTRY *uniform)(GLint, GLsizei, const GLfloat*))
130 char buffer[2*sizeof(vs_vector_template)];
131 GLuint vs, fs;
132 GLuint program;
133 GLint loc_a, loc_b, loc_c;
134 GLint loc_b2;
136 snprintf(buffer, sizeof(buffer), vs_vector_template,
137 glsl_type, glsl_type, glsl_type, glsl_type);
138 vs = compile_shader(GL_VERTEX_SHADER_ARB, buffer);
140 snprintf(buffer, sizeof(buffer), fs_vector_template,
141 glsl_type, suffix);
142 fs = compile_shader(GL_FRAGMENT_SHADER_ARB, buffer);
144 program = link_program(vs, fs);
146 glUseProgramObjectARB(program);
147 loc_a = glGetUniformLocationARB(program, "a");
148 loc_b = glGetUniformLocationARB(program, "b");
149 loc_c = glGetUniformLocationARB(program, "c");
150 loc_b2 = glGetUniformLocationARB(program, "b[2]");
151 printf("locations: a: %i b: %i c: %i b[2]: %i\n", loc_a, loc_b, loc_c, loc_b);
153 expect_error(GL_NO_ERROR, "Type %s: Sanity check", glsl_type);
154 uniform(loc_a, 0, lots_of_zeros);
155 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to a", glsl_type);
156 uniform(loc_a, 1, lots_of_zeros);
157 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to a", glsl_type);
158 uniform(loc_a, 2, lots_of_zeros);
159 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = 2 to a", glsl_type);
160 uniform(loc_a, 1024, lots_of_zeros);
161 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = 1024 to a", glsl_type);
163 uniform(loc_b, 0, lots_of_zeros);
164 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b", glsl_type);
165 uniform(loc_b, 1, lots_of_zeros);
166 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to b", glsl_type);
167 uniform(loc_b, 4, lots_of_zeros);
168 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to b", glsl_type);
170 /* Note: The following are out of bound for the array,
171 * but the spec situation is a bit unclear as to whether errors
172 * should be generated.
174 * Issue #32 of the ARB_shader_objects spec suggests errors
175 * should be generated when writing out-of-bounds on arrays,
176 * but this is not reflected in the OpenGL spec.
178 * The main point of these tests is to make sure the driver
179 * does not introduce memory errors by accessing internal arrays
180 * out of bounds.
182 uniform(loc_b, 5, lots_of_zeros);
183 (void) glGetError(); /* Eat generated error, if any */
185 uniform(loc_c, 0, lots_of_zeros);
186 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to c", glsl_type);
187 uniform(loc_c, 1, lots_of_zeros);
188 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to c", glsl_type);
189 uniform(loc_c, 4, lots_of_zeros);
190 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to c", glsl_type);
192 /* Out of bounds; see comment above */
193 uniform(loc_c, 5, lots_of_zeros);
194 (void) glGetError(); /* Eat generated error, if any */
196 uniform(loc_b2, 0, lots_of_zeros);
197 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b[2]", glsl_type);
198 uniform(loc_b2, 2, lots_of_zeros);
199 expect_error(GL_NO_ERROR, "Type %s: Write count = 2 to b[2]", glsl_type);
201 /* Out of bounds; see comment above */
202 uniform(loc_b2, 1024, lots_of_zeros);
203 (void) glGetError(); /* Eat generated error, if any */
205 glDeleteObjectARB(fs);
206 glDeleteObjectARB(vs);
207 glDeleteObjectARB(program);
210 static const char vs_matrix_template[] =
211 "uniform mat4 a;\n"
212 "uniform mat4 b[4];\n"
213 "uniform mat4 c[4];\n"
214 "varying vec4 v;\n"
215 "void main() {\n"
216 " mat4 m = a + b[3] + c[0] + c[1] + c[2] + c[3];\n"
217 " v = m * vec4(1.0, 1.0, 1.0, 1.0);\n"
218 " gl_Position = vec4(0,0,0,1);\n"
219 "}\n";
221 static const char fs_matrix_template[] =
222 "varying vec4 v;\n"
223 "void main() {\n"
224 " gl_FragColor = v;\n"
225 "}\n";
228 static void test_matrix(void)
230 GLuint vs, fs;
231 GLuint program;
232 GLint loc_a, loc_b, loc_c;
233 GLint loc_b2;
234 const char * glsl_type = "mat4";
236 vs = compile_shader(GL_VERTEX_SHADER_ARB, vs_matrix_template);
237 fs = compile_shader(GL_FRAGMENT_SHADER_ARB, fs_matrix_template);
238 program = link_program(vs, fs);
240 glUseProgramObjectARB(program);
241 loc_a = glGetUniformLocationARB(program, "a");
242 loc_b = glGetUniformLocationARB(program, "b");
243 loc_c = glGetUniformLocationARB(program, "c");
244 loc_b2 = glGetUniformLocationARB(program, "b[2]");
245 printf("locations: a: %i b: %i c: %i b[2]: %i\n", loc_a, loc_b, loc_c, loc_b);
247 expect_error(GL_NO_ERROR, "Type %s: Sanity check", glsl_type);
249 glUniformMatrix4fvARB(loc_b, 0, GL_FALSE, lots_of_zeros);
250 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b", glsl_type);
251 glUniformMatrix4fvARB(loc_b, 1, GL_FALSE, lots_of_zeros);
252 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to b", glsl_type);
253 glUniformMatrix4fvARB(loc_b, 4, GL_FALSE, lots_of_zeros);
254 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to b", glsl_type);
256 /* Out of bounds; see comment above */
257 glUniformMatrix4fvARB(loc_b, 5, GL_FALSE, lots_of_zeros);
258 (void) glGetError(); /* Eat generated error, if any */
260 glUniformMatrix4fvARB(loc_c, 0, GL_FALSE, lots_of_zeros);
261 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to c", glsl_type);
262 glUniformMatrix4fvARB(loc_c, 1, GL_FALSE, lots_of_zeros);
263 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to c", glsl_type);
264 glUniformMatrix4fvARB(loc_c, 4, GL_FALSE, lots_of_zeros);
265 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to c", glsl_type);
267 /* Out of bounds; see comment above */
268 glUniformMatrix4fvARB(loc_c, 5, GL_FALSE, lots_of_zeros);
269 (void) glGetError(); /* Eat generated error, if any */
271 glUniformMatrix4fvARB(loc_b2, 0, GL_FALSE, lots_of_zeros);
272 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b[2]", glsl_type);
273 glUniformMatrix4fvARB(loc_b2, 2, GL_FALSE, lots_of_zeros);
274 expect_error(GL_NO_ERROR, "Type %s: Write count = 2 to b[2]", glsl_type);
276 /* Out of bounds; see comment above */
277 glUniformMatrix4fvARB(loc_b2, INT_MAX, GL_FALSE, lots_of_zeros);
278 (void) glGetError(); /* Eat generated error, if any */
280 glUniformMatrix4fvARB(loc_a, 0, GL_FALSE, lots_of_zeros);
281 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to a", glsl_type);
282 glUniformMatrix4fvARB(loc_a, 1, GL_FALSE, lots_of_zeros);
283 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to a", glsl_type);
284 glUniformMatrix4fvARB(loc_a, 2, GL_FALSE, lots_of_zeros);
285 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = 2 to a", glsl_type);
286 glUniformMatrix4fvARB(loc_a, INT_MAX, GL_FALSE, lots_of_zeros);
287 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = INT_MAX to a", glsl_type);
289 glDeleteObjectARB(fs);
290 glDeleteObjectARB(vs);
291 glDeleteObjectARB(program);
294 enum piglit_result
295 piglit_display(void)
297 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
299 test_matrix();
301 test_vector("float", ", 0, 0, 0", glUniform1fvARB);
302 test_vector("vec2", ", 0, 0", glUniform2fvARB);
303 test_vector("vec3", ", 0", glUniform3fvARB);
304 test_vector("vec4", "", glUniform4fvARB);
306 return PIGLIT_PASS;
309 void
310 piglit_init(int argc, char **argv)
312 if (!piglit_is_extension_supported("GL_ARB_shader_objects") || !piglit_is_extension_supported("GL_ARB_vertex_shader") || !piglit_is_extension_supported("GL_ARB_fragment_shader")) {
313 printf("Requires ARB_shader_objects and ARB_{vertex,fragment}_shader\n");
314 piglit_report_result(PIGLIT_SKIP);