| Auto-Submit | +1 |
| Commit-Queue | +1 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
Mainly some nits, overall LGTM. Thank you.
static_cast<size_t>(constraints.min_bytes_per_row()), stride_from_size);Nit, just call checked_stride.ValueOrDie() instead of stride_from_size. But see my another suggestion below.
base::CheckedNumeric<size_t> checked_rounded_stride = stride_value;I think you can just say checked_stride.Max(constraints.min_bytes_per_row()).
if (!checked_rounded_stride.IsValid()) {
return std::nullopt;
}Nit, I think the beautiful thing of CheckedNumeric is that you can continue the calculation but check IsValid() at the very end.
base::CheckedNumeric<size_t> checked_plane_size = stride;Nit, you can copy a CheckedNumeric from another CheckedNumeric without needing to do ValueOrDie() here.
layout.stride = stride;Ditto, you may just use ValueOrDie() here to make the assumption more obvious.
if (format == viz::MultiPlaneFormat::kNV12) {It looks like the uv_plane_offset and uv_plane_size are only calculated and used for NV12, I may suggest adding a comment here to explain it.
DCHECK(sysmem_token);I think you may also want to log and return false here.
.has_value()) {Nit, this .has_value() call seems not necessary.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Auto-Submit | +1 |
| Commit-Queue | +1 |
static_cast<size_t>(constraints.min_bytes_per_row()), stride_from_size);Nit, just call checked_stride.ValueOrDie() instead of stride_from_size. But see my another suggestion below.
Changed to use `CheckedNumeric` throughout, and checked at the end.
base::CheckedNumeric<size_t> checked_rounded_stride = stride_value;I think you can just say checked_stride.Max(constraints.min_bytes_per_row()).
Done
if (!checked_rounded_stride.IsValid()) {
return std::nullopt;
}Nit, I think the beautiful thing of CheckedNumeric is that you can continue the calculation but check IsValid() at the very end.
I didn't look at it closely before, this is quite cool!
Nit, you can copy a CheckedNumeric from another CheckedNumeric without needing to do ValueOrDie() here.
Done
Ditto, you may just use ValueOrDie() here to make the assumption more obvious.
Done
It looks like the uv_plane_offset and uv_plane_size are only calculated and used for NV12, I may suggest adding a comment here to explain it.
Added in the struct definition.
I think you may also want to log and return false here.
Yup, missed that. Done.
Nit, this .has_value() call seems not necessary.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
11 is the latest approved patch-set.
The change was submitted with unreviewed changes in the following files:
```
The name of the file: ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc
Insertions: 30, Deletions: 42.
@@ -59,6 +59,9 @@
size_t stride = 0;
size_t plane_offset = 0;
size_t plane_size = 0;
+
+ // uv_plane_offset and uv_plane_size are only calculated and used for NV12
+ // (2-plane YUV).
size_t uv_plane_offset = 0;
size_t uv_plane_size = 0;
};
@@ -79,59 +82,42 @@
base::CheckedNumeric<size_t> checked_stride = size.width();
checked_stride *= GetBytesPerPixel(format);
- if (!checked_stride.IsValid()) {
- return std::nullopt;
- }
+ checked_stride =
+ checked_stride.Max(static_cast<size_t>(constraints.min_bytes_per_row()));
- size_t stride_from_size = checked_stride.ValueOrDie();
- size_t stride_value = std::max(
- static_cast<size_t>(constraints.min_bytes_per_row()), stride_from_size);
size_t divisor = constraints.bytes_per_row_divisor();
- base::CheckedNumeric<size_t> checked_rounded_stride = stride_value;
if (divisor > 0) {
- checked_rounded_stride += divisor - 1;
- if (!checked_rounded_stride.IsValid()) {
- return std::nullopt;
- }
- size_t rounded_stride_value = checked_rounded_stride.ValueOrDie();
- checked_rounded_stride = (rounded_stride_value / divisor) * divisor;
+ checked_stride = ((checked_stride + divisor - 1) / divisor) * divisor;
}
- if (!checked_rounded_stride.IsValid()) {
- return std::nullopt;
- }
- size_t stride = checked_rounded_stride.ValueOrDie();
- base::CheckedNumeric<size_t> checked_plane_size = stride;
- checked_plane_size *= size.height();
- if (!checked_plane_size.IsValid()) {
- return std::nullopt;
- }
- size_t plane_size = checked_plane_size.ValueOrDie();
+ base::CheckedNumeric<size_t> checked_plane_size =
+ checked_stride * size.height();
+ base::CheckedNumeric<size_t> checked_plane_end =
+ checked_plane_size + vmo_usable_start;
- base::CheckedNumeric<size_t> checked_plane_end = vmo_usable_start;
- checked_plane_end += plane_size;
+ // Checking validity of `checked_plane_end` also implicitly validates
+ // `checked_plane_size` and `checked_stride`, because they are chained
+ // together.
if (!checked_plane_end.IsValid() ||
checked_plane_end.ValueOrDie() > buffer_size) {
return std::nullopt;
}
BufferLayout layout;
- layout.stride = stride;
+ layout.stride = checked_stride.ValueOrDie();
layout.plane_offset = vmo_usable_start;
- layout.plane_size = plane_size;
+ layout.plane_size = checked_plane_size.ValueOrDie();
if (format == viz::MultiPlaneFormat::kNV12) {
- base::CheckedNumeric<size_t> checked_uv_plane_offset = vmo_usable_start;
- checked_uv_plane_offset += plane_size;
- base::CheckedNumeric<size_t> checked_uv_plane_size = stride;
- checked_uv_plane_size *= (static_cast<size_t>(size.height()) + 1) / 2;
- if (!checked_uv_plane_offset.IsValid() ||
- !checked_uv_plane_size.IsValid()) {
- return std::nullopt;
- }
+ base::CheckedNumeric<size_t> checked_uv_plane_offset = checked_plane_end;
+ base::CheckedNumeric<size_t> checked_uv_plane_size =
+ checked_stride * ((static_cast<size_t>(size.height()) + 1) / 2);
+ base::CheckedNumeric<size_t> checked_uv_plane_end =
+ checked_uv_plane_offset + checked_uv_plane_size;
- base::CheckedNumeric<size_t> checked_uv_plane_end = checked_uv_plane_offset;
- checked_uv_plane_end += checked_uv_plane_size;
+ // Checking validity of `checked_uv_plane_end` also implicitly validates
+ // `checked_uv_plane_size` and `checked_uv_plane_offset` because they are
+ // chained together.
if (!checked_uv_plane_end.IsValid() ||
checked_uv_plane_end.ValueOrDie() > buffer_size) {
return std::nullopt;
@@ -358,7 +344,10 @@
if (size.IsEmpty()) {
// Buffer collection that doesn't have explicit size is expected to be
// shared with other participants, who will determine the actual image size.
- DCHECK(sysmem_token);
+ if (!sysmem_token) {
+ LOG(ERROR) << "Sysmem token is required for empty size.";
+ return false;
+ }
// Set nominal size of 1x1, which will be used only for
// vkSetBufferCollectionConstraintsFUCHSIA(). The actual size of the
@@ -494,10 +483,9 @@
// Verify that the image size and layout fit within the allocated buffer.
if (!CalculateBufferLayout(
- buffers_info_.settings().image_format_constraints(), size, format_,
- buffers_info_.buffers()[buffer_index].vmo_usable_start(),
- buffer_size_)
- .has_value()) {
+ buffers_info_.settings().image_format_constraints(), size, format_,
+ buffers_info_.buffers()[buffer_index].vmo_usable_start(),
+ buffer_size_)) {
LOG(ERROR) << "Requested VkImage size " << size.ToString()
<< " exceeds the allocated sysmem buffer size.";
return false;
```
[fuchsia][flatland] Validate image size and layout
Validate gfx::Size and format in Initialize, CreateNativePixmap, and
CreateVkImage to prevent buffer overflows.
- Unify size validation and layout calculation in the
CalculateBufferLayout helper using checked math.
- Verify that the computed image layout fits within the allocated buffer
size.
- Keep layout boundary checks and early size/format checks as graceful
failures (returning nullptr or false) to prevent DoS from untrusted
inputs.
- Convert Vulkan memory requirements checks to CHECKs (crash on
unexpected system values).
TAG=agy
CONV=c64f46f9-7333-4bcf-8497-788ae27b1ce7
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |