diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2016-11-08 11:06:05 -0800 |
---|---|---|
committer | Emil Velikov <emil.l.velikov@gmail.com> | 2016-11-23 13:59:41 +0000 |
commit | dfd6b765ba25a3f9a40abbb85111e1369495beb7 (patch) | |
tree | 45bfe592d9c88be54dfbf5f482d72e67438770b0 | |
parent | a4b67f664e6a52898e681b35ca769e1fd206a4d1 (diff) | |
download | external_mesa3d-dfd6b765ba25a3f9a40abbb85111e1369495beb7.zip external_mesa3d-dfd6b765ba25a3f9a40abbb85111e1369495beb7.tar.gz external_mesa3d-dfd6b765ba25a3f9a40abbb85111e1369495beb7.tar.bz2 |
glcpp: Handle '#version 0' and other invalid values
The #version directive can only handle decimal constants. Enforce that
the value is a decimal constant.
Section 3.3 (Preprocessor) of the GLSL 4.50 spec says:
The language version a shader is written to is specified by
#version number profile opt
where number must be a version of the language, following the same
convention as __VERSION__ above.
The same section also says:
__VERSION__ will substitute a decimal integer reflecting the version
number of the OpenGL shading language.
Use a separate flag to track whether or not the #version line has been
encountered. Any possible sentinel (0 is currently used) could be
specified in a #version directive. This would lead to trying to
(internally) redefine __VERSION__. Since there is no parser location
for this addition, NULL is passed. This eventually results in a NULL
dereference and a segfault.
Attempts to use -1 as the sentinel would also fail if '#version
4294967295' or '#version 18446744073709551615' were used. We should
have piglit tests for both of these.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97420
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
Cc: mesa-stable@lists.freedesktop.org
Cc: Juan A. Suarez Romero <jasuarez@igalia.com>
Cc: Karol Herbst <karolherbst@gmail.com>
(cherry picked from commit e85a747e294762785df2ce8a299c153254c6fca2)
-rw-r--r-- | src/compiler/glsl/glcpp/glcpp-parse.y | 25 | ||||
-rw-r--r-- | src/compiler/glsl/glcpp/glcpp.h | 9 |
2 files changed, 28 insertions, 6 deletions
diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index 4fd1448..7656325 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -176,7 +176,7 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value); * (such as the <HASH> and <DEFINE> start conditions in the lexer). */ %token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS %token PASTE -%type <ival> INTEGER operator SPACE integer_constant +%type <ival> INTEGER operator SPACE integer_constant version_constant %type <expression_value> expression %type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA %type <string_list> identifier_list @@ -424,14 +424,14 @@ control_line_success: | HASH_TOKEN ENDIF { _glcpp_parser_skip_stack_pop (parser, & @1); } NEWLINE -| HASH_TOKEN VERSION_TOKEN integer_constant NEWLINE { - if (parser->version != 0) { +| HASH_TOKEN VERSION_TOKEN version_constant NEWLINE { + if (parser->version_set) { glcpp_error(& @1, parser, "#version must appear on the first line"); } _glcpp_parser_handle_version_declaration(parser, $3, NULL, true); } -| HASH_TOKEN VERSION_TOKEN integer_constant IDENTIFIER NEWLINE { - if (parser->version != 0) { +| HASH_TOKEN VERSION_TOKEN version_constant IDENTIFIER NEWLINE { + if (parser->version_set) { glcpp_error(& @1, parser, "#version must appear on the first line"); } _glcpp_parser_handle_version_declaration(parser, $3, $4, true); @@ -470,6 +470,17 @@ integer_constant: $$ = $1; } +version_constant: + INTEGER_STRING { + /* Both octal and hexadecimal constants begin with 0. */ + if ($1[0] == '0' && $1[1] != '\0') { + glcpp_error(&@1, parser, "invalid #version \"%s\" (not a decimal constant)", $1); + $$ = 0; + } else { + $$ = strtoll($1, NULL, 10); + } + } + expression: integer_constant { $$.value = $1; @@ -1376,6 +1387,7 @@ glcpp_parser_create(glcpp_extension_iterator extensions, void *state, gl_api api parser->state = state; parser->api = api; parser->version = 0; + parser->version_set = false; parser->has_new_line_number = 0; parser->new_line_number = 1; @@ -2318,10 +2330,11 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio const char *es_identifier, bool explicitly_set) { - if (parser->version != 0) + if (parser->version_set) return; parser->version = version; + parser->version_set = true; add_builtin_define (parser, "__VERSION__", version); diff --git a/src/compiler/glsl/glcpp/glcpp.h b/src/compiler/glsl/glcpp/glcpp.h index cab4374..fcee812 100644 --- a/src/compiler/glsl/glcpp/glcpp.h +++ b/src/compiler/glsl/glcpp/glcpp.h @@ -207,6 +207,15 @@ struct glcpp_parser { void *state; gl_api api; unsigned version; + + /** + * Has the #version been set? + * + * A separate flag is used because any possible sentinel value in + * \c ::version could also be set by a #version line. + */ + bool version_set; + bool has_new_line_number; int new_line_number; bool has_new_source_number; |