Fix uninitialized use of TIntermediate::resource (#2424)

TIntermediate was constructed without initializing any of the `resources` fields,
and `TProgram::linkStage()` was not calling `TIntermediate::setLimits()`
after constructing new `TIntermediate`s for non-first stages.

Fields of `resources` were then read in `TIntermediate::finalCheck()`
triggering undefined behavior.

This CL makes three changes:
(1) `TIntermediate::setLimits()` is now called for non-first stages by
    copying the `firstIntermediate`'s limits. This ensures that the
    `resources` fields is initialized, fixing the bug.
(2) `TIntermediate::resources` is now wrapped in a `MustBeAssigned<>`
    helper struct, asserting in non-release builds that this field is
    always initialized before reading.
(3) `TIntermediate::resources` is now zero-initialized, so that if
    the `TIntermediate::resources` field is not set in a release build
    (and so the `assert()` will be disabled) behavior is still
    deterministic.

Fixes #2423
This commit is contained in:
Ben Clayton 2020-10-19 22:21:12 +01:00 committed by GitHub
parent f4f1d8a352
commit 5b99b448b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 4 deletions

View file

@ -2016,7 +2016,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
intermediate[stage] = new TIntermediate(stage,
firstIntermediate->getVersion(),
firstIntermediate->getProfile());
intermediate[stage]->setLimits(firstIntermediate->getLimits());
// The new TIntermediate must use the same origin as the original TIntermediates.
// Otherwise linking will fail due to different coordinate systems.