Report details of at most 3 #pragma shader_stage conflicts This avoids a potential memory blowup when reporting errors. Google-internal bug 536206565
diff --git a/glslc/test/pragma_shader_stage.py b/glslc/test/pragma_shader_stage.py index c0f1f08..d2522b2 100644 --- a/glslc/test/pragma_shader_stage.py +++ b/glslc/test/pragma_shader_stage.py
@@ -540,6 +540,38 @@ @inside_glslc_testsuite('PragmaShaderStage') +class TestPSSExcessStageConflictReportingCutoffAt3(expect.ErrorMessage): + """Tests that if there are more than 3 shader-stage pragma + stage conflicts, the details are only provided for three of + them, with an additional trailing count of how many more exist.""" + + shader = FileShader( + """#version 310 es + #pragma shader_stage(idontknow) + #pragma shader_stage(vertex) + void main() { + gl_Position = vec4(1.); + } + #pragma shader_stage(fragment) + #pragma shader_stage(fragment) + #pragma shader_stage(fragment) + #pragma shader_stage(fragment) + """, '.glsl') + glslc_args = ['-c', shader] + expected_error = [ + shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " + "#pragma: 'idontknow'\n", + shader, ":3: error: '#pragma': conflicting stages for 'shader_stage' " + "#pragma: 'vertex' (was 'idontknow' at ", shader, ':2)\n', + shader, ":7: error: '#pragma': conflicting stages for 'shader_stage' " + "#pragma: 'fragment' (was 'idontknow' at ", shader, ':2)\n', + shader, ":8: error: '#pragma': conflicting stages for 'shader_stage' " + "#pragma: 'fragment' (was 'idontknow' at ", shader, ':2)\n', + "error: ... 2 more conflicting 'shader_stage' pragmas\n", + ] + + +@inside_glslc_testsuite('PragmaShaderStage') class TestSpacesAroundPSS(expect.ValidObjectFile): """Tests that spaces around #pragma shader_stage() works."""
diff --git a/libshaderc_util/src/compiler.cc b/libshaderc_util/src/compiler.cc index bbd5469..89d9914 100644 --- a/libshaderc_util/src/compiler.cc +++ b/libshaderc_util/src/compiler.cc
@@ -714,20 +714,30 @@ first_pragma_stage.str() + "'\n"; } + constexpr size_t kMaxReportedConflicts = 3; + size_t num_conflicts = 0; for (size_t i = 1; i < stages.size(); ++i) { const string_piece& current_stage = std::get<2>(stages[i]); if (current_stage != first_pragma_stage) { - const string_piece& current_filename = std::get<0>(stages[i]); - const std::string current_line = std::to_string(std::get<1>(stages[i])); - error_message += current_filename.str() + ":" + current_line + - ": error: '#pragma': conflicting stages for " - "'shader_stage' #pragma: '" + - current_stage.str() + "' (was '" + - first_pragma_stage.str() + "' at " + - first_pragma_filename.str() + ":" + first_pragma_line + - ")\n"; + ++num_conflicts; + if (num_conflicts <= kMaxReportedConflicts) { + const string_piece& current_filename = std::get<0>(stages[i]); + const std::string current_line = std::to_string(std::get<1>(stages[i])); + error_message += current_filename.str() + ":" + current_line + + ": error: '#pragma': conflicting stages for " + "'shader_stage' #pragma: '" + + current_stage.str() + "' (was '" + + first_pragma_stage.str() + "' at " + + first_pragma_filename.str() + ":" + first_pragma_line + + ")\n"; + } } } + if (num_conflicts > kMaxReportedConflicts) { + error_message += "error: ... " + + std::to_string(num_conflicts - kMaxReportedConflicts) + + " more conflicting 'shader_stage' pragmas\n"; + } return std::make_pair(error_message.empty() ? stage : EShLangCount, error_message);