diff --git a/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp b/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp index 70d3716900..f64b0917e6 100644 --- a/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp +++ b/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp @@ -32,6 +32,16 @@ extern "C" { #include #include +#define SET_ERROR_VALUE_IF_ERROR(expression, error_value) \ + ({ \ + auto maybe_error = expression; \ + if (maybe_error.is_error()) [[unlikely]] { \ + set_error(error_value); \ + return; \ + } \ + maybe_error.release_value(); \ + }) + namespace Web::WebGL { static Vector null_terminated_string(StringView string) @@ -122,45 +132,36 @@ void WebGL2RenderingContextImpl::tex_image3d(WebIDL::UnsignedLong target, WebIDL { m_context->make_current(); - void const* src_data_ptr = nullptr; - size_t buffer_size = 0; + ReadonlyBytes src_data_span; if (src_data) { - auto const& viewed_array_buffer = src_data->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - src_data_ptr = byte_buffer.data() + src_data->byte_offset(); - buffer_size = src_data->byte_length(); + src_data_span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, /* src_offset= */ 0), GL_INVALID_OPERATION); } - glTexImage3DRobustANGLE(target, level, internalformat, width, height, depth, border, format, type, buffer_size, src_data_ptr); + + glTexImage3DRobustANGLE(target, level, internalformat, width, height, depth, border, format, type, src_data_span.size(), src_data_span.data()); } void WebGL2RenderingContextImpl::tex_image3d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long internalformat, WebIDL::Long width, WebIDL::Long height, WebIDL::Long depth, WebIDL::Long border, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, GC::Root src_data, WebIDL::UnsignedLongLong src_offset) { m_context->make_current(); - void const* src_data_ptr = nullptr; - size_t buffer_size = 0; + ReadonlyBytes src_data_span; if (src_data) { - auto const& viewed_array_buffer = src_data->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - src_data_ptr = byte_buffer.data() + src_offset; - buffer_size = src_data->byte_length(); + src_data_span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset), GL_INVALID_OPERATION); } - glTexImage3DRobustANGLE(target, level, internalformat, width, height, depth, border, format, type, buffer_size, src_data_ptr); + + glTexImage3DRobustANGLE(target, level, internalformat, width, height, depth, border, format, type, src_data_span.size(), src_data_span.data()); } void WebGL2RenderingContextImpl::tex_sub_image3d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long xoffset, WebIDL::Long yoffset, WebIDL::Long zoffset, WebIDL::Long width, WebIDL::Long height, WebIDL::Long depth, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, GC::Root src_data, WebIDL::UnsignedLongLong src_offset) { m_context->make_current(); - void const* pixels_ptr = nullptr; - size_t buffer_size = 0; + ReadonlyBytes src_data_span; if (src_data) { - auto const& viewed_array_buffer = src_data->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - pixels_ptr = byte_buffer.data() + src_offset; - buffer_size = src_data->byte_length(); + src_data_span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset), GL_INVALID_OPERATION); } - glTexSubImage3DRobustANGLE(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, buffer_size, pixels_ptr); + + glTexSubImage3DRobustANGLE(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, src_data_span.size(), src_data_span.data()); } void WebGL2RenderingContextImpl::uniform1ui(GC::Root location, WebIDL::UnsignedLong v0) @@ -229,18 +230,18 @@ void WebGL2RenderingContextImpl::clear_bufferfv(WebIDL::UnsignedLong buffer, Web m_context->make_current(); m_context->notify_content_will_change(); - auto span = span_from_float32_list(values); + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset), GL_INVALID_VALUE); switch (buffer) { case GL_COLOR: - if (src_offset + 4 > span.size()) { + if (span.size() < 4) { set_error(GL_INVALID_VALUE); return; } break; case GL_DEPTH: case GL_STENCIL: - if (src_offset + 1 > span.size()) { + if (span.size() < 1) { set_error(GL_INVALID_VALUE); return; } @@ -251,7 +252,6 @@ void WebGL2RenderingContextImpl::clear_bufferfv(WebIDL::UnsignedLong buffer, Web return; } - span = span.slice(src_offset); glClearBufferfv(buffer, drawbuffer, span.data()); needs_to_present(); } @@ -261,19 +261,18 @@ void WebGL2RenderingContextImpl::clear_bufferiv(WebIDL::UnsignedLong buffer, Web m_context->make_current(); m_context->notify_content_will_change(); - auto span = span_from_int32_list(values); - auto count = span.size(); + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset), GL_INVALID_VALUE); switch (buffer) { case GL_COLOR: - if (src_offset + 4 > count) { + if (span.size() < 4) { set_error(GL_INVALID_VALUE); return; } break; case GL_DEPTH: case GL_STENCIL: - if (src_offset + 1 > count) { + if (span.size() < 1) { set_error(GL_INVALID_VALUE); return; } @@ -284,7 +283,6 @@ void WebGL2RenderingContextImpl::clear_bufferiv(WebIDL::UnsignedLong buffer, Web return; } - span = span.slice(src_offset); glClearBufferiv(buffer, drawbuffer, span.data()); needs_to_present(); } @@ -294,17 +292,17 @@ void WebGL2RenderingContextImpl::clear_bufferuiv(WebIDL::UnsignedLong buffer, We m_context->make_current(); m_context->notify_content_will_change(); - auto span = span_from_uint32_list(values); + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_uint32_list(values, src_offset), GL_INVALID_VALUE); switch (buffer) { case GL_COLOR: - if (src_offset + 4 > span.size()) { + if (span.size() < 4) { set_error(GL_INVALID_VALUE); return; } break; case GL_DEPTH: case GL_STENCIL: - if (src_offset + 1 > span.size()) { + if (span.size() < 1) { set_error(GL_INVALID_VALUE); return; } @@ -315,7 +313,6 @@ void WebGL2RenderingContextImpl::clear_bufferuiv(WebIDL::UnsignedLong buffer, We return; } - span = span.slice(src_offset); glClearBufferuiv(buffer, drawbuffer, span.data()); needs_to_present(); } @@ -729,119 +726,44 @@ void WebGL2RenderingContextImpl::buffer_data(WebIDL::UnsignedLong target, GC::Ro { m_context->make_current(); - void const* ptr = nullptr; - size_t byte_size = 0; - if (src_data->is_typed_array_base()) { - auto& typed_array_base = static_cast(*src_data->raw_object()); - ptr = typed_array_base.viewed_array_buffer()->buffer().data() + typed_array_base.byte_offset(); - byte_size = src_data->byte_length(); - } else if (src_data->is_data_view()) { - auto& data_view = static_cast(*src_data->raw_object()); - ptr = data_view.viewed_array_buffer()->buffer().data(); - byte_size = data_view.viewed_array_buffer()->byte_length(); - } else if (src_data->is_array_buffer()) { - auto& array_buffer = static_cast(*src_data->raw_object()); - ptr = array_buffer.buffer().data(); - byte_size = array_buffer.byte_length(); - } else { - VERIFY_NOT_REACHED(); - } - glBufferData(target, byte_size, ptr, usage); + auto data = MUST(get_offset_span(*src_data, /* src_offset= */ 0)); + glBufferData(target, data.size(), data.data(), usage); } void WebGL2RenderingContextImpl::buffer_sub_data(WebIDL::UnsignedLong target, WebIDL::LongLong dst_byte_offset, GC::Root src_data) { m_context->make_current(); - void const* ptr = nullptr; - size_t byte_size = 0; - if (src_data->is_typed_array_base()) { - auto& typed_array_base = static_cast(*src_data->raw_object()); - ptr = typed_array_base.viewed_array_buffer()->buffer().data() + typed_array_base.byte_offset(); - byte_size = src_data->byte_length(); - } else if (src_data->is_data_view()) { - auto& data_view = static_cast(*src_data->raw_object()); - ptr = data_view.viewed_array_buffer()->buffer().data(); - byte_size = data_view.viewed_array_buffer()->byte_length(); - } else if (src_data->is_array_buffer()) { - auto& array_buffer = static_cast(*src_data->raw_object()); - ptr = array_buffer.buffer().data(); - byte_size = array_buffer.byte_length(); - } else { - VERIFY_NOT_REACHED(); - } - glBufferSubData(target, dst_byte_offset, byte_size, ptr); + auto data = MUST(get_offset_span(*src_data, /* src_offset= */ 0)); + glBufferSubData(target, dst_byte_offset, data.size(), data.data()); } void WebGL2RenderingContextImpl::buffer_data(WebIDL::UnsignedLong target, GC::Root src_data, WebIDL::UnsignedLong usage, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong length) { m_context->make_current(); - VERIFY(src_data); - auto const& viewed_array_buffer = src_data->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - auto src_data_length = src_data->byte_length(); - auto src_data_element_size = src_data->element_size(); - u8 const* buffer_ptr = byte_buffer.data(); - - u64 copy_length = length == 0 ? src_data_length - src_offset : length; - copy_length *= src_data_element_size; - - if (src_offset > src_data_length) { - set_error(GL_INVALID_VALUE); - return; - } - - if (src_offset + copy_length > src_data_length) { - set_error(GL_INVALID_VALUE); - return; - } - - buffer_ptr += src_offset * src_data_element_size; - glBufferData(target, copy_length, buffer_ptr, usage); + auto span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset, length), GL_INVALID_VALUE); + glBufferData(target, span.size(), span.data(), usage); } void WebGL2RenderingContextImpl::buffer_sub_data(WebIDL::UnsignedLong target, WebIDL::LongLong dst_byte_offset, GC::Root src_data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong length) { m_context->make_current(); - VERIFY(src_data); - auto const& viewed_array_buffer = src_data->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - auto src_data_length = src_data->byte_length(); - auto src_data_element_size = src_data->element_size(); - u8 const* buffer_ptr = byte_buffer.data(); - - u64 copy_length = length == 0 ? src_data_length - src_offset : length; - copy_length *= src_data_element_size; - - if (src_offset > src_data_length) { - set_error(GL_INVALID_VALUE); - return; - } - - if (src_offset + copy_length > src_data_length) { - set_error(GL_INVALID_VALUE); - return; - } - - buffer_ptr += src_offset * src_data_element_size; - glBufferSubData(target, dst_byte_offset, copy_length, buffer_ptr); + auto span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset, length), GL_INVALID_VALUE); + glBufferSubData(target, dst_byte_offset, span.size(), span.data()); } void WebGL2RenderingContextImpl::tex_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long internalformat, WebIDL::Long width, WebIDL::Long height, WebIDL::Long border, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, GC::Root pixels) { m_context->make_current(); - void const* pixels_ptr = nullptr; - size_t buffer_size = 0; + ReadonlyBytes pixels_span; if (pixels) { - auto const& viewed_array_buffer = pixels->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - pixels_ptr = byte_buffer.data() + pixels->byte_offset(); - buffer_size = pixels->byte_length(); + pixels_span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*pixels, /* src_offset= */ 0), GL_INVALID_OPERATION); } - glTexImage2DRobustANGLE(target, level, internalformat, width, height, border, format, type, buffer_size, pixels_ptr); + + glTexImage2DRobustANGLE(target, level, internalformat, width, height, border, format, type, pixels_span.size(), pixels_span.data()); } void WebGL2RenderingContextImpl::tex_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long internalformat, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, TexImageSource source) @@ -859,15 +781,12 @@ void WebGL2RenderingContextImpl::tex_sub_image2d(WebIDL::UnsignedLong target, We { m_context->make_current(); - void const* pixels_ptr = nullptr; - size_t buffer_size = 0; + ReadonlyBytes pixels_span; if (pixels) { - auto const& viewed_array_buffer = pixels->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - pixels_ptr = byte_buffer.data() + pixels->byte_offset(); - buffer_size = pixels->byte_length(); + pixels_span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*pixels, /* src_offset= */ 0), GL_INVALID_OPERATION); } - glTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, type, buffer_size, pixels_ptr); + + glTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, type, pixels_span.size(), pixels_span.data()); } void WebGL2RenderingContextImpl::tex_sub_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long xoffset, WebIDL::Long yoffset, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, TexImageSource source) @@ -897,15 +816,12 @@ void WebGL2RenderingContextImpl::tex_image2d(WebIDL::UnsignedLong target, WebIDL { m_context->make_current(); - void const* pixels_ptr = nullptr; - size_t buffer_size = 0; + ReadonlyBytes pixels_span; if (src_data) { - auto const& viewed_array_buffer = src_data->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - pixels_ptr = byte_buffer.data() + src_offset; - buffer_size = src_data->byte_length(); + pixels_span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset), GL_INVALID_OPERATION); } - glTexImage2DRobustANGLE(target, level, internalformat, width, height, border, format, type, buffer_size, pixels_ptr); + + glTexImage2DRobustANGLE(target, level, internalformat, width, height, border, format, type, pixels_span.size(), pixels_span.data()); } void WebGL2RenderingContextImpl::tex_sub_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long xoffset, WebIDL::Long yoffset, WebIDL::Long width, WebIDL::Long height, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, TexImageSource source) @@ -924,63 +840,28 @@ void WebGL2RenderingContextImpl::tex_sub_image2d(WebIDL::UnsignedLong target, We { m_context->make_current(); - void const* pixels_ptr = nullptr; - size_t buffer_size = 0; + ReadonlyBytes pixels_span; if (src_data) { - auto const& viewed_array_buffer = src_data->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - pixels_ptr = byte_buffer.data() + src_data->byte_offset() + src_offset; - buffer_size = src_data->byte_length(); + pixels_span = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset), GL_INVALID_OPERATION); } - glTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, type, buffer_size, pixels_ptr); + + glTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, type, pixels_span.size(), pixels_span.data()); } void WebGL2RenderingContextImpl::compressed_tex_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::UnsignedLong internalformat, WebIDL::Long width, WebIDL::Long height, WebIDL::Long border, GC::Root src_data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length_override) { m_context->make_current(); - u8 const* pixels_ptr = src_data->viewed_array_buffer()->buffer().data(); - size_t count = src_data->byte_length(); - auto src_data_element_size = src_data->element_size(); - - if ((src_offset * src_data_element_size) + src_length_override > count) { - set_error(GL_INVALID_VALUE); - return; - } - - pixels_ptr += src_data->byte_offset(); - pixels_ptr += src_offset * src_data_element_size; - if (src_length_override == 0) { - count -= src_offset; - } else { - count = src_length_override; - } - - glCompressedTexImage2DRobustANGLE(target, level, internalformat, width, height, border, count, src_data->byte_length(), pixels_ptr); + auto pixels = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset, src_length_override), GL_INVALID_VALUE); + glCompressedTexImage2DRobustANGLE(target, level, internalformat, width, height, border, pixels.size(), pixels.size(), pixels.data()); } void WebGL2RenderingContextImpl::compressed_tex_sub_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long xoffset, WebIDL::Long yoffset, WebIDL::Long width, WebIDL::Long height, WebIDL::UnsignedLong format, GC::Root src_data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length_override) { m_context->make_current(); - u8 const* pixels_ptr = src_data->viewed_array_buffer()->buffer().data(); - size_t count = src_data->byte_length(); - auto src_data_element_size = src_data->element_size(); - - if ((src_offset * src_data_element_size) + src_length_override > count) { - set_error(GL_INVALID_VALUE); - return; - } - - pixels_ptr += src_data->byte_offset(); - pixels_ptr += src_offset * src_data_element_size; - if (src_length_override == 0) { - count -= src_offset; - } else { - count = src_length_override; - } - - glCompressedTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, count, src_data->byte_length(), pixels_ptr); + auto pixels = SET_ERROR_VALUE_IF_ERROR(get_offset_span(*src_data, src_offset, src_length_override), GL_INVALID_VALUE); + glCompressedTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, pixels.size(), pixels.size(), pixels.data()); } void WebGL2RenderingContextImpl::uniform1fv(GC::Root location, Float32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) @@ -990,189 +871,109 @@ void WebGL2RenderingContextImpl::uniform1fv(GC::Root locat if (!location) return; - auto span = span_from_float32_list(values); - auto count = span.size(); - if (src_offset + src_length > count) { - set_error(GL_INVALID_VALUE); - return; - } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform1fv(location->handle(), count, span.data()); + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE); + glUniform1fv(location->handle(), span.size(), span.data()); } -void WebGL2RenderingContextImpl::uniform2fv(GC::Root location, Float32List v, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) +void WebGL2RenderingContextImpl::uniform2fv(GC::Root location, Float32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) { m_context->make_current(); if (!location) return; - auto span = span_from_float32_list(v); - auto count = span.size(); - if (src_offset + src_length > span.size()) { + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % 2 != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform2fv(location->handle(), count / 2, span.data()); + glUniform2fv(location->handle(), span.size() / 2, span.data()); } -void WebGL2RenderingContextImpl::uniform3fv(GC::Root location, Float32List v, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) +void WebGL2RenderingContextImpl::uniform3fv(GC::Root location, Float32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) { m_context->make_current(); if (!location) return; - auto span = span_from_float32_list(v); - auto count = span.size(); - if (src_offset + src_length > count) { + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % 3 != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform3fv(location->handle(), count / 3, span.data()); + glUniform3fv(location->handle(), span.size() / 3, span.data()); } -void WebGL2RenderingContextImpl::uniform4fv(GC::Root location, Float32List v, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) +void WebGL2RenderingContextImpl::uniform4fv(GC::Root location, Float32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) { m_context->make_current(); if (!location) return; - auto span = span_from_float32_list(v); - auto count = span.size(); - if (src_offset + src_length > count) { + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % 4 != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform4fv(location->handle(), count / 4, span.data()); + glUniform4fv(location->handle(), span.size() / 4, span.data()); } -void WebGL2RenderingContextImpl::uniform1iv(GC::Root location, Int32List v, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) +void WebGL2RenderingContextImpl::uniform1iv(GC::Root location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) { m_context->make_current(); if (!location) return; - auto span = span_from_int32_list(v); - auto count = span.size(); - if (src_offset + src_length > count) { - set_error(GL_INVALID_VALUE); - return; - } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform1iv(location->handle(), count / 1, span.data()); + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE); + glUniform1iv(location->handle(), span.size(), span.data()); } -void WebGL2RenderingContextImpl::uniform2iv(GC::Root location, Int32List v, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) +void WebGL2RenderingContextImpl::uniform2iv(GC::Root location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) { m_context->make_current(); if (!location) return; - auto span = span_from_int32_list(v); - auto count = span.size(); - if (src_offset + src_length > count) { + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % 2 != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform2iv(location->handle(), count / 2, span.data()); + glUniform2iv(location->handle(), span.size() / 2, span.data()); } -void WebGL2RenderingContextImpl::uniform3iv(GC::Root location, Int32List v, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) +void WebGL2RenderingContextImpl::uniform3iv(GC::Root location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) { m_context->make_current(); if (!location) return; - auto span = span_from_int32_list(v); - auto count = span.size(); - if (src_offset + src_length > count) { + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % 3 != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform3iv(location->handle(), count / 3, span.data()); + glUniform3iv(location->handle(), span.size() / 3, span.data()); } -void WebGL2RenderingContextImpl::uniform4iv(GC::Root location, Int32List v, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) +void WebGL2RenderingContextImpl::uniform4iv(GC::Root location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) { m_context->make_current(); if (!location) return; - auto span = span_from_int32_list(v); - auto count = span.size(); - if (src_offset + src_length > count) { + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % 4 != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniform4iv(location->handle(), count / 4, span.data()); + glUniform4iv(location->handle(), span.size() / 4, span.data()); } void WebGL2RenderingContextImpl::uniform_matrix2fv(GC::Root location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) @@ -1182,23 +983,13 @@ void WebGL2RenderingContextImpl::uniform_matrix2fv(GC::Root (count * matrix_size)) { + constexpr auto matrix_size = 2 * 2; + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % matrix_size != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniformMatrix2fv(location->handle(), count, transpose, span.data()); + glUniformMatrix2fv(location->handle(), span.size() / matrix_size, transpose, span.data()); } void WebGL2RenderingContextImpl::uniform_matrix3fv(GC::Root location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) @@ -1208,23 +999,13 @@ void WebGL2RenderingContextImpl::uniform_matrix3fv(GC::Root (count * matrix_size)) { + constexpr auto matrix_size = 3 * 3; + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % matrix_size != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniformMatrix3fv(location->handle(), count, transpose, span.data()); + glUniformMatrix3fv(location->handle(), span.size() / matrix_size, transpose, span.data()); } void WebGL2RenderingContextImpl::uniform_matrix4fv(GC::Root location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length) @@ -1234,23 +1015,13 @@ void WebGL2RenderingContextImpl::uniform_matrix4fv(GC::Root (count * matrix_size)) { + constexpr auto matrix_size = 4 * 4; + auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE); + if (span.size() % matrix_size != 0) [[unlikely]] { set_error(GL_INVALID_VALUE); return; } - - span = span.slice(src_offset); - if (src_length == 0) { - count -= src_offset; - } else { - count = src_length; - } - - glUniformMatrix4fv(location->handle(), count, transpose, span.data()); + glUniformMatrix4fv(location->handle(), span.size() / matrix_size, transpose, span.data()); } void WebGL2RenderingContextImpl::read_pixels(WebIDL::Long x, WebIDL::Long y, WebIDL::Long width, WebIDL::Long height, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, GC::Root pixels) @@ -1261,8 +1032,8 @@ void WebGL2RenderingContextImpl::read_pixels(WebIDL::Long x, WebIDL::Long y, Web return; } - void* ptr = pixels->viewed_array_buffer()->buffer().data() + pixels->byte_offset(); - glReadPixelsRobustANGLE(x, y, width, height, format, type, pixels->byte_length(), nullptr, nullptr, nullptr, ptr); + auto span = MUST(get_offset_span(*pixels, /* src_offset= */ 0)); + glReadPixelsRobustANGLE(x, y, width, height, format, type, span.size(), nullptr, nullptr, nullptr, span.data()); } void WebGL2RenderingContextImpl::active_texture(WebIDL::UnsignedLong texture) @@ -3095,7 +2866,7 @@ void WebGL2RenderingContextImpl::vertex_attrib1fv(WebIDL::UnsignedLong index, Fl { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 1) { set_error(GL_INVALID_VALUE); return; @@ -3107,7 +2878,7 @@ void WebGL2RenderingContextImpl::vertex_attrib2fv(WebIDL::UnsignedLong index, Fl { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 2) { set_error(GL_INVALID_VALUE); return; @@ -3119,7 +2890,7 @@ void WebGL2RenderingContextImpl::vertex_attrib3fv(WebIDL::UnsignedLong index, Fl { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 3) { set_error(GL_INVALID_VALUE); return; @@ -3131,7 +2902,7 @@ void WebGL2RenderingContextImpl::vertex_attrib4fv(WebIDL::UnsignedLong index, Fl { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 4) { set_error(GL_INVALID_VALUE); return; diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h b/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h index 8768f9f561..1f1d045d2a 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h @@ -6,8 +6,10 @@ #pragma once +#include #include #include +#include #include namespace Web::WebGL { @@ -28,25 +30,76 @@ public: virtual OpenGLContext& context() = 0; virtual bool ext_texture_filter_anisotropic_extension_enabled() const = 0; - static Span span_from_float32_list(Float32List& float32_list) + template + static ErrorOr> get_offset_span(Span src_span, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length_override = 0) { - if (float32_list.has>()) - return float32_list.get>(); - return float32_list.get>()->data(); + Checked length = src_offset; + length += src_length_override; + if (length.has_overflow() || length.value_unchecked() > src_span.size()) [[unlikely]] + return Error::from_errno(EINVAL); + + if (src_length_override == 0) + return src_span.slice(src_offset, src_span.size() - src_offset); + + return src_span.slice(src_offset, src_length_override); } - static Span span_from_int32_list(Int32List& int32_list) + template + static ErrorOr> get_offset_span(GC::Ref src_data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length_override = 0) { - if (int32_list.has>()) - return int32_list.get>(); - return int32_list.get>()->data(); + auto buffer_size = src_data->byte_length(); + if (buffer_size % sizeof(T) != 0) [[unlikely]] + return Error::from_errno(EINVAL); + + auto raw_object = src_data->raw_object(); + + if (auto* array_buffer = as_if(*raw_object)) { + return TRY(get_offset_span(array_buffer->buffer().span(), src_offset, src_length_override)).reinterpret(); + } + + if (auto* data_view = as_if(*raw_object)) { + return TRY(get_offset_span(data_view->viewed_array_buffer()->buffer().span(), src_offset, src_length_override)).reinterpret(); + } + + // NOTE: This has to be done because src_offset is the number of elements to offset by, not the number of bytes. +#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ + if (auto* typed_array = as_if(*raw_object)) { \ + return TRY(get_offset_span(typed_array->data(), src_offset, src_length_override)).reinterpret(); \ + } + JS_ENUMERATE_TYPED_ARRAYS +#undef __JS_ENUMERATE + + VERIFY_NOT_REACHED(); } - static Span span_from_uint32_list(Uint32List& int32_list) + static ErrorOr> span_from_float32_list(Float32List& float32_list, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length_override = 0) { - if (int32_list.has>()) - return int32_list.get>(); - return int32_list.get>()->data(); + if (float32_list.has>()) { + auto& vector = float32_list.get>(); + return get_offset_span(vector.span(), src_offset, src_length_override); + } + auto& buffer = float32_list.get>(); + return get_offset_span(buffer->data(), src_offset, src_length_override); + } + + static ErrorOr> span_from_int32_list(Int32List& int32_list, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length_override = 0) + { + if (int32_list.has>()) { + auto& vector = int32_list.get>(); + return get_offset_span(vector.span(), src_offset, src_length_override); + } + auto& buffer = int32_list.get>(); + return get_offset_span(buffer->data(), src_offset, src_length_override); + } + + static ErrorOr> span_from_uint32_list(Uint32List& uint32_list, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length_override = 0) + { + if (uint32_list.has>()) { + auto& vector = uint32_list.get>(); + return get_offset_span(vector.span(), src_offset, src_length_override); + } + auto& buffer = uint32_list.get>(); + return get_offset_span(buffer->data(), src_offset, src_length_override); } struct ConvertedTexture { diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp b/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp index 567eb8d2d5..9b95430b52 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp @@ -59,66 +59,32 @@ void WebGLRenderingContextImpl::buffer_data(WebIDL::UnsignedLong target, GC::Roo { m_context->make_current(); - void const* ptr = nullptr; - size_t byte_size = 0; - if (data->is_typed_array_base()) { - auto& typed_array_base = static_cast(*data->raw_object()); - ptr = typed_array_base.viewed_array_buffer()->buffer().data() + typed_array_base.byte_offset(); - byte_size = data->byte_length(); - } else if (data->is_data_view()) { - auto& data_view = static_cast(*data->raw_object()); - ptr = data_view.viewed_array_buffer()->buffer().data(); - byte_size = data_view.viewed_array_buffer()->byte_length(); - } else if (data->is_array_buffer()) { - auto& array_buffer = static_cast(*data->raw_object()); - ptr = array_buffer.buffer().data(); - byte_size = array_buffer.byte_length(); - } else { - VERIFY_NOT_REACHED(); - } - glBufferData(target, byte_size, ptr, usage); + auto span = MUST(get_offset_span(*data, /* src_offset= */ 0)); + glBufferData(target, span.size(), span.data(), usage); } void WebGLRenderingContextImpl::buffer_sub_data(WebIDL::UnsignedLong target, WebIDL::LongLong offset, GC::Root data) { m_context->make_current(); - void const* ptr = nullptr; - size_t byte_size = 0; - if (data->is_typed_array_base()) { - auto& typed_array_base = static_cast(*data->raw_object()); - ptr = typed_array_base.viewed_array_buffer()->buffer().data() + typed_array_base.byte_offset(); - byte_size = data->byte_length(); - } else if (data->is_data_view()) { - auto& data_view = static_cast(*data->raw_object()); - ptr = data_view.viewed_array_buffer()->buffer().data(); - byte_size = data_view.viewed_array_buffer()->byte_length(); - } else if (data->is_array_buffer()) { - auto& array_buffer = static_cast(*data->raw_object()); - ptr = array_buffer.buffer().data(); - byte_size = array_buffer.byte_length(); - } else { - VERIFY_NOT_REACHED(); - } - glBufferSubData(target, offset, byte_size, ptr); + auto span = MUST(get_offset_span(*data, /* src_offset= */ 0)); + glBufferSubData(target, offset, span.size(), span.data()); } void WebGLRenderingContextImpl::compressed_tex_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::UnsignedLong internalformat, WebIDL::Long width, WebIDL::Long height, WebIDL::Long border, GC::Root data) { m_context->make_current(); - void const* ptr = data->viewed_array_buffer()->buffer().data() + data->byte_offset(); - size_t byte_size = data->byte_length(); - glCompressedTexImage2DRobustANGLE(target, level, internalformat, width, height, border, byte_size, byte_size, ptr); + auto span = MUST(get_offset_span(*data, /* src_offset= */ 0)); + glCompressedTexImage2DRobustANGLE(target, level, internalformat, width, height, border, span.size(), span.size(), span.data()); } void WebGLRenderingContextImpl::compressed_tex_sub_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long xoffset, WebIDL::Long yoffset, WebIDL::Long width, WebIDL::Long height, WebIDL::UnsignedLong format, GC::Root data) { m_context->make_current(); - void const* ptr = data->viewed_array_buffer()->buffer().data() + data->byte_offset(); - size_t byte_size = data->byte_length(); - glCompressedTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, byte_size, byte_size, ptr); + auto span = MUST(get_offset_span(*data, /* src_offset= */ 0)); + glCompressedTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, span.size(), span.size(), span.data()); } void WebGLRenderingContextImpl::read_pixels(WebIDL::Long x, WebIDL::Long y, WebIDL::Long width, WebIDL::Long height, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, GC::Root pixels) @@ -129,23 +95,16 @@ void WebGLRenderingContextImpl::read_pixels(WebIDL::Long x, WebIDL::Long y, WebI return; } - void* ptr = pixels->viewed_array_buffer()->buffer().data() + pixels->byte_offset(); - glReadPixelsRobustANGLE(x, y, width, height, format, type, pixels->byte_length(), nullptr, nullptr, nullptr, ptr); + auto span = MUST(get_offset_span(*pixels, /* src_offset= */ 0)); + glReadPixelsRobustANGLE(x, y, width, height, format, type, span.size(), nullptr, nullptr, nullptr, span.data()); } void WebGLRenderingContextImpl::tex_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long internalformat, WebIDL::Long width, WebIDL::Long height, WebIDL::Long border, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, GC::Root pixels) { m_context->make_current(); - void const* pixels_ptr = nullptr; - size_t buffer_size = 0; - if (pixels) { - auto const& viewed_array_buffer = pixels->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - pixels_ptr = byte_buffer.data() + pixels->byte_offset(); - buffer_size = pixels->byte_length(); - } - glTexImage2DRobustANGLE(target, level, internalformat, width, height, border, format, type, buffer_size, pixels_ptr); + auto span = MUST(get_offset_span(*pixels, /* src_offset= */ 0)); + glTexImage2DRobustANGLE(target, level, internalformat, width, height, border, format, type, span.size(), span.data()); } void WebGLRenderingContextImpl::tex_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long internalformat, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, TexImageSource source) @@ -163,15 +122,8 @@ void WebGLRenderingContextImpl::tex_sub_image2d(WebIDL::UnsignedLong target, Web { m_context->make_current(); - void const* pixels_ptr = nullptr; - size_t buffer_size = 0; - if (pixels) { - auto const& viewed_array_buffer = pixels->viewed_array_buffer(); - auto const& byte_buffer = viewed_array_buffer->buffer(); - pixels_ptr = byte_buffer.data() + pixels->byte_offset(); - buffer_size = pixels->byte_length(); - } - glTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, type, buffer_size, pixels_ptr); + auto span = MUST(get_offset_span(*pixels, /* src_offset= */ 0)); + glTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height, format, type, span.size(), span.data()); } void WebGLRenderingContextImpl::tex_sub_image2d(WebIDL::UnsignedLong target, WebIDL::Long level, WebIDL::Long xoffset, WebIDL::Long yoffset, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, TexImageSource source) @@ -192,7 +144,7 @@ void WebGLRenderingContextImpl::uniform1fv(GC::Root locati if (!location) return; - auto span = span_from_float32_list(v); + auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0)); glUniform1fv(location->handle(), span.size(), span.data()); } @@ -202,7 +154,11 @@ void WebGLRenderingContextImpl::uniform2fv(GC::Root locati if (!location) return; - auto span = span_from_float32_list(v); + auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0)); + if (span.size() % 2 != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniform2fv(location->handle(), span.size() / 2, span.data()); } @@ -212,7 +168,11 @@ void WebGLRenderingContextImpl::uniform3fv(GC::Root locati if (!location) return; - auto span = span_from_float32_list(v); + auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0)); + if (span.size() % 3 != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniform3fv(location->handle(), span.size() / 3, span.data()); } @@ -222,7 +182,11 @@ void WebGLRenderingContextImpl::uniform4fv(GC::Root locati if (!location) return; - auto span = span_from_float32_list(v); + auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0)); + if (span.size() % 4 != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniform4fv(location->handle(), span.size() / 4, span.data()); } @@ -232,8 +196,8 @@ void WebGLRenderingContextImpl::uniform1iv(GC::Root locati if (!location) return; - auto span = span_from_int32_list(v); - glUniform1iv(location->handle(), span.size() / 1, span.data()); + auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0)); + glUniform1iv(location->handle(), span.size(), span.data()); } void WebGLRenderingContextImpl::uniform2iv(GC::Root location, Int32List v) @@ -242,7 +206,11 @@ void WebGLRenderingContextImpl::uniform2iv(GC::Root locati if (!location) return; - auto span = span_from_int32_list(v); + auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0)); + if (span.size() % 2 != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniform2iv(location->handle(), span.size() / 2, span.data()); } @@ -252,7 +220,11 @@ void WebGLRenderingContextImpl::uniform3iv(GC::Root locati if (!location) return; - auto span = span_from_int32_list(v); + auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0)); + if (span.size() % 3 != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniform3iv(location->handle(), span.size() / 3, span.data()); } @@ -262,7 +234,11 @@ void WebGLRenderingContextImpl::uniform4iv(GC::Root locati if (!location) return; - auto span = span_from_int32_list(v); + auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0)); + if (span.size() % 4 != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniform4iv(location->handle(), span.size() / 4, span.data()); } @@ -272,8 +248,12 @@ void WebGLRenderingContextImpl::uniform_matrix2fv(GC::Root if (!location) return; - auto matrix_size = 2 * 2; - auto span = span_from_float32_list(value); + constexpr auto matrix_size = 2 * 2; + auto span = MUST(span_from_float32_list(value, /* src_offset= */ 0)); + if (span.size() % matrix_size != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniformMatrix2fv(location->handle(), span.size() / matrix_size, transpose, span.data()); } @@ -283,8 +263,12 @@ void WebGLRenderingContextImpl::uniform_matrix3fv(GC::Root if (!location) return; - auto matrix_size = 3 * 3; - auto span = span_from_float32_list(value); + constexpr auto matrix_size = 3 * 3; + auto span = MUST(span_from_float32_list(value, /* src_offset= */ 0)); + if (span.size() % matrix_size != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniformMatrix3fv(location->handle(), span.size() / matrix_size, transpose, span.data()); } @@ -294,8 +278,12 @@ void WebGLRenderingContextImpl::uniform_matrix4fv(GC::Root if (!location) return; - auto matrix_size = 4 * 4; - auto span = span_from_float32_list(value); + constexpr auto matrix_size = 4 * 4; + auto span = MUST(span_from_float32_list(value, /* src_offset= */ 0)); + if (span.size() % matrix_size != 0) [[unlikely]] { + set_error(GL_INVALID_VALUE); + return; + } glUniformMatrix4fv(location->handle(), span.size() / matrix_size, transpose, span.data()); } @@ -1954,7 +1942,7 @@ void WebGLRenderingContextImpl::vertex_attrib1fv(WebIDL::UnsignedLong index, Flo { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 1) { set_error(GL_INVALID_VALUE); return; @@ -1966,7 +1954,7 @@ void WebGLRenderingContextImpl::vertex_attrib2fv(WebIDL::UnsignedLong index, Flo { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 2) { set_error(GL_INVALID_VALUE); return; @@ -1978,7 +1966,7 @@ void WebGLRenderingContextImpl::vertex_attrib3fv(WebIDL::UnsignedLong index, Flo { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 3) { set_error(GL_INVALID_VALUE); return; @@ -1990,7 +1978,7 @@ void WebGLRenderingContextImpl::vertex_attrib4fv(WebIDL::UnsignedLong index, Flo { m_context->make_current(); - auto span = span_from_float32_list(values); + auto span = MUST(span_from_float32_list(values, /* src_offset= */ 0)); if (span.size() < 4) { set_error(GL_INVALID_VALUE); return;