diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp index b5a2bb3ce8..f5c64019fd 100644 --- a/src/libANGLE/Texture.cpp +++ b/src/libANGLE/Texture.cpp @@ -1367,7 +1367,34 @@ GLint Texture::getLevelMemorySize(TextureTarget target, GLint level) const void Texture::signalDirtyStorage(InitState initState) { - mState.mInitState = initState; + // SECURITY: Do not blindly promote the aggregate to Initialized. Callers + // such as setImage()/setCompressedImage()/copyTexture()/generateMipmap() + // pass Initialized for the level they just defined while OTHER mip levels' + // ImageDesc.initState may still be MayNeedInit. Promoting here makes + // ensureInitialized() early-exit (Texture.cpp) and lets uninitialized GPU + // memory be sampled. The aggregate may only become Initialized via the + // per-level scan that setImageDesc()/setImageDescChain() already perform, + // or by re-scanning here. + if (initState == InitState::MayNeedInit) + { + mState.mInitState = InitState::MayNeedInit; + } + else + { + bool allInitialized = true; + for (const ImageDesc &desc : mState.mImageDescs) + { + if (desc.initState == InitState::MayNeedInit) + { + allInitialized = false; + break; + } + } + if (allInitialized) + { + mState.mInitState = InitState::Initialized; + } + } invalidateCompletenessCache(); mState.mCachedSamplerFormatValid = false; onStateChange(angle::SubjectMessage::SubjectChanged);