diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index 2f9c8632..3d2a52a1 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -1143,6 +1143,7 @@ namespace MobileGL::MG_Impl::GLImpl { const FramebufferAttachmentType attachmentType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment); if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return; + if (!FramebufferImpl::ValidateColorAttachmentInRange(attachmentType, functionName)) return; if (!TextureImpl::ValidateTextureName(texture, true)) return; if (texture == 0) { @@ -1239,6 +1240,7 @@ namespace MobileGL::MG_Impl::GLImpl { FramebufferTarget framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target); RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(renderbuffertarget); if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return; + if (!FramebufferImpl::ValidateColorAttachmentInRange(attachmentType, "FramebufferRenderbuffer_State")) return; if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return; auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); @@ -1283,6 +1285,8 @@ namespace MobileGL::MG_Impl::GLImpl { FramebufferAttachmentType attachmentType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment); RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(renderbuffertarget); if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return; + if (!FramebufferImpl::ValidateColorAttachmentInRange(attachmentType, "NamedFramebufferRenderbuffer_State")) + return; if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return; if (renderbuffer == 0) { diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp index fbfa6bab..9fdde7ab 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp @@ -7,6 +7,7 @@ // End of Source File Header #include "Validators.h" +#include #include #include #include @@ -60,6 +61,26 @@ namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl { return true; } + Bool ValidateColorAttachmentInRange(FramebufferAttachmentType attachment, const char* caller) { + const auto first = static_cast(FramebufferAttachmentType::Color0); + const auto index = static_cast(attachment); + if (index < first) return true; + const auto colorIndex = index - first; + const auto limit = static_cast( + MG_Backend::pActiveBackendObject ? MG_Backend::pActiveBackendObject->GetDynamicParameters() + .MaxColorAttachments + : static_cast(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS)); + if (colorIndex >= limit) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique( + "MG_Impl/GLImpl/FramebufferImpl", caller, + std::format("Colour attachment {} is beyond GL_MAX_COLOR_ATTACHMENTS ({}).", colorIndex, limit))); + return false; + } + return true; + } + Bool ValidateRenderbufferTarget(RenderbufferTarget target) { if (target == RenderbufferTarget::Unknown) { using namespace MG_Util; diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h index 7e5216e4..a95b64ac 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h @@ -14,6 +14,10 @@ namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl { Bool ValidateFramebufferTarget(FramebufferTarget target); Bool ValidateFramebufferName(Uint index, Bool allowZero = true); Bool ValidateFramebufferAttachmentType(FramebufferAttachmentType attachment); + // GL_COLOR_ATTACHMENTn is a token per n up to 31, but only the first GL_MAX_COLOR_ATTACHMENTS of + // them name an attachment point of a framebuffer object; the rest are INVALID_OPERATION for the + // attaching entry points (GL 4.6 core 9.2.7). Non-colour attachments pass through unchanged. + Bool ValidateColorAttachmentInRange(FramebufferAttachmentType attachment, const char* caller); Bool ValidateRenderbufferTarget(RenderbufferTarget target); Bool ValidateRenderbufferName(Uint index, Bool allowZero = true); } // namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl diff --git a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp index 5778cc0a..17b4b637 100644 --- a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp +++ b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp @@ -121,6 +121,27 @@ namespace MobileGL::MG_Impl::GLImpl { return static_cast(size * MG_Util::GetGLTypeSize(type)); } + // glBindVertexBuffers / glVertexArrayVertexBuffers take a range of binding points, and a + // range that runs past the last one is INVALID_OPERATION rather than the INVALID_VALUE a + // single out-of-range index gets (GL 4.6 core 10.3.1). + static bool ValidateVertexBindingRange(GLuint first, GLsizei count, const char* funcName) { + if (count < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", funcName, "count must be non-negative.")); + return false; + } + if (static_cast(first) + static_cast(count) > + VertexArrayImpl::GetMaxVertexAttribBindings()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", funcName, + "first + count exceeds GL_MAX_VERTEX_ATTRIB_BINDINGS.")); + return false; + } + return true; + } + static bool ValidateVertexBindingIndex(GLuint bindingindex, const char* funcName) { if (bindingindex >= VertexArrayImpl::GetMaxVertexAttribBindings()) { MG_State::pGLContext->RecordError( @@ -408,6 +429,7 @@ namespace MobileGL::MG_Impl::GLImpl { const GLintptr* offsets, const GLsizei* strides) { auto vao = GetNamedVertexArrayObject_State(vaobj, "VertexArrayVertexBuffers_State"); if (!vao) return; + if (!ValidateVertexBindingRange(first, count, "VertexArrayVertexBuffers_State")) return; for (GLsizei i = 0; i < count; ++i) { if (!buffers) { VertexBufferBinding_State(vao, first + i, 0, 0, 16, "VertexArrayVertexBuffers_State"); @@ -1209,6 +1231,7 @@ namespace MobileGL::MG_Impl::GLImpl { const GLsizei* strides) { auto vao = GetBoundVertexArrayOrError("BindVertexBuffers"); if (!vao) return; + if (!ValidateVertexBindingRange(first, count, "BindVertexBuffers")) return; for (GLsizei i = 0; i < count; ++i) { if (!buffers) { VertexBufferBinding_State(vao, first + i, 0, 0, 16, "BindVertexBuffers");