diff mbox series

[FFmpeg-devel,v2] lavc/vvc: Validate explicit subpic locations

Message ID 20240825175027.40160-1-post@frankplowman.com
State New
Headers show
Series [FFmpeg-devel,v2] lavc/vvc: Validate explicit subpic locations | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Frank Plowman Aug. 25, 2024, 5:45 p.m. UTC
Implement the missing requirements from H.266 (V3) p. 106 on the
position and size of subpictures whose dimensions are provided
explicitly.

Signed-off-by: Frank Plowman <post@frankplowman.com>
---
Changes since v1 (20240824092827.68912-1-post@frankplowman.com):
* Use temporary variables and AV_CEIL_RSHIFT to make bound calculations
  more readable.
* Fix bounds on size.  The calculated values are minimums, not
  maximums as in v1.  Additionally, fix an integer overflow in the bound
  calculations.

 libavcodec/cbs_h266_syntax_template.c | 49 +++++++++++++++++++++------
 1 file changed, 38 insertions(+), 11 deletions(-)

Comments

Nuo Mi Aug. 31, 2024, 7:15 a.m. UTC | #1
On Mon, Aug 26, 2024 at 1:50 AM Frank Plowman <post@frankplowman.com> wrote:

> Implement the missing requirements from H.266 (V3) p. 106 on the
> position and size of subpictures whose dimensions are provided
> explicitly.
>
Applied this and "[FFmpeg-devel] [PATCH] lavc/vvc: Prevent OOB access in
subpic_tiles"
Thank you, Frank.

>
> Signed-off-by: Frank Plowman <post@frankplowman.com>
> ---
> Changes since v1 (20240824092827.68912-1-post@frankplowman.com):
> * Use temporary variables and AV_CEIL_RSHIFT to make bound calculations
>   more readable.
> * Fix bounds on size.  The calculated values are minimums, not
>   maximums as in v1.  Additionally, fix an integer overflow in the bound
>   calculations.
>
>  libavcodec/cbs_h266_syntax_template.c | 49 +++++++++++++++++++++------
>  1 file changed, 38 insertions(+), 11 deletions(-)
>
> diff --git a/libavcodec/cbs_h266_syntax_template.c
> b/libavcodec/cbs_h266_syntax_template.c
> index 9c37996947..a8f5af04d0 100644
> --- a/libavcodec/cbs_h266_syntax_template.c
> +++ b/libavcodec/cbs_h266_syntax_template.c
> @@ -1061,7 +1061,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx,
> RWContext *rw,
>      unsigned int ctb_log2_size_y, min_cb_log2_size_y,
>                   min_qt_log2_size_intra_y, min_qt_log2_size_inter_y,
>                   ctb_size_y, max_num_merge_cand, tmp_width_val,
> tmp_height_val;
> -    uint8_t qp_bd_offset;
> +    uint8_t qp_bd_offset, sub_width_c, sub_height_c;
>
>      static const uint8_t h266_sub_width_c[] = {
>          1, 2, 2, 1
> @@ -1089,6 +1089,9 @@ static int FUNC(sps)(CodedBitstreamContext *ctx,
> RWContext *rw,
>
>      u(3, sps_max_sublayers_minus1, 0, VVC_MAX_SUBLAYERS - 1);
>      u(2, sps_chroma_format_idc, 0, 3);
> +    sub_width_c = h266_sub_width_c[current->sps_chroma_format_idc];
> +    sub_height_c = h266_sub_height_c[current->sps_chroma_format_idc];
> +
>      u(2, sps_log2_ctu_size_minus5, 0, 3);
>      ctb_log2_size_y = current->sps_log2_ctu_size_minus5 + 5;
>      ctb_size_y = 1 << ctb_log2_size_y;
> @@ -1110,8 +1113,6 @@ static int FUNC(sps)(CodedBitstreamContext *ctx,
> RWContext *rw,
>
>      flag(sps_conformance_window_flag);
>      if (current->sps_conformance_window_flag) {
> -        uint8_t sub_width_c =
> h266_sub_width_c[current->sps_chroma_format_idc];
> -        uint8_t sub_height_c =
> h266_sub_height_c[current->sps_chroma_format_idc];
>          uint16_t width = current->sps_pic_width_max_in_luma_samples /
> sub_width_c;
>          uint16_t height = current->sps_pic_height_max_in_luma_samples /
> sub_height_c;
>          ue(sps_conf_win_left_offset, 0, width);
> @@ -1160,19 +1161,37 @@ static int FUNC(sps)(CodedBitstreamContext *ctx,
> RWContext *rw,
>              }
>              for (i = 1; i <= current->sps_num_subpics_minus1; i++) {
>                  if (!current->sps_subpic_same_size_flag) {
> -                    if (current->sps_pic_width_max_in_luma_samples >
> ctb_size_y)
> -                        ubs(wlen, sps_subpic_ctu_top_left_x[i], 1, i);
> -                    else
> +                    if (current->sps_pic_width_max_in_luma_samples >
> ctb_size_y) {
> +                        const unsigned int win_right_edge =
> +                            current->sps_pic_width_max_in_luma_samples
> +                          - current->sps_conf_win_right_offset *
> sub_width_c;
> +                        us(wlen, sps_subpic_ctu_top_left_x[i], 0,
> +                           AV_CEIL_RSHIFT(win_right_edge,
> ctb_log2_size_y) - 1,
> +                           1, i);
> +                    } else
>                          infer(sps_subpic_ctu_top_left_x[i], 0);
>                      if (current->sps_pic_height_max_in_luma_samples >
> -                        ctb_size_y)
> -                        ubs(hlen, sps_subpic_ctu_top_left_y[i], 1, i);
> -                    else
> +                        ctb_size_y) {
> +                        const unsigned int win_bottom_edge =
> +                            current->sps_pic_height_max_in_luma_samples
> +                          - current->sps_conf_win_bottom_offset *
> sub_height_c;
> +                        us(hlen, sps_subpic_ctu_top_left_y[i], 0,
> +                           AV_CEIL_RSHIFT(win_bottom_edge,
> ctb_log2_size_y) - 1,
> +                           1, i);
> +                    } else
>                          infer(sps_subpic_ctu_top_left_y[i], 0);
>                      if (i < current->sps_num_subpics_minus1 &&
>                          current->sps_pic_width_max_in_luma_samples >
>                          ctb_size_y) {
> -                        ubs(wlen, sps_subpic_width_minus1[i], 1, i);
> +                        const unsigned int win_left_edge =
> +                            current->sps_conf_win_left_offset *
> sub_width_c;
> +                        const unsigned int win_left_edge_ctus =
> +                            AV_CEIL_RSHIFT(win_left_edge,
> ctb_log2_size_y);
> +                        us(wlen, sps_subpic_width_minus1[i],
> +                           win_left_edge_ctus >
> current->sps_subpic_ctu_top_left_x[i]
> +                               ? win_left_edge_ctus -
> current->sps_subpic_ctu_top_left_x[i]
> +                               : 0,
> +                           MAX_UINT_BITS(wlen), 1, i);
>                      } else {
>                          infer(sps_subpic_width_minus1[i],
>                                tmp_width_val -
> @@ -1181,7 +1200,15 @@ static int FUNC(sps)(CodedBitstreamContext *ctx,
> RWContext *rw,
>                      if (i < current->sps_num_subpics_minus1 &&
>                          current->sps_pic_height_max_in_luma_samples >
>                          ctb_size_y) {
> -                        ubs(hlen, sps_subpic_height_minus1[i], 1, i);
> +                        const unsigned int win_top_edge =
> +                            current->sps_conf_win_top_offset *
> sub_height_c;
> +                        const unsigned int win_top_edge_ctus =
> +                            AV_CEIL_RSHIFT(win_top_edge, ctb_log2_size_y);
> +                        us(hlen, sps_subpic_height_minus1[i],
> +                           win_top_edge_ctus >
> current->sps_subpic_ctu_top_left_y[i]
> +                               ? win_top_edge_ctus -
> current->sps_subpic_ctu_top_left_y[i]
> +                               : 0,
> +                           MAX_UINT_BITS(wlen), 1, i);
>                      } else {
>                          infer(sps_subpic_height_minus1[i],
>                                tmp_height_val -
> --
> 2.46.0
>
>
diff mbox series

Patch

diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c
index 9c37996947..a8f5af04d0 100644
--- a/libavcodec/cbs_h266_syntax_template.c
+++ b/libavcodec/cbs_h266_syntax_template.c
@@ -1061,7 +1061,7 @@  static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
     unsigned int ctb_log2_size_y, min_cb_log2_size_y,
                  min_qt_log2_size_intra_y, min_qt_log2_size_inter_y,
                  ctb_size_y, max_num_merge_cand, tmp_width_val, tmp_height_val;
-    uint8_t qp_bd_offset;
+    uint8_t qp_bd_offset, sub_width_c, sub_height_c;
 
     static const uint8_t h266_sub_width_c[] = {
         1, 2, 2, 1
@@ -1089,6 +1089,9 @@  static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
 
     u(3, sps_max_sublayers_minus1, 0, VVC_MAX_SUBLAYERS - 1);
     u(2, sps_chroma_format_idc, 0, 3);
+    sub_width_c = h266_sub_width_c[current->sps_chroma_format_idc];
+    sub_height_c = h266_sub_height_c[current->sps_chroma_format_idc];
+
     u(2, sps_log2_ctu_size_minus5, 0, 3);
     ctb_log2_size_y = current->sps_log2_ctu_size_minus5 + 5;
     ctb_size_y = 1 << ctb_log2_size_y;
@@ -1110,8 +1113,6 @@  static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
 
     flag(sps_conformance_window_flag);
     if (current->sps_conformance_window_flag) {
-        uint8_t sub_width_c = h266_sub_width_c[current->sps_chroma_format_idc];
-        uint8_t sub_height_c = h266_sub_height_c[current->sps_chroma_format_idc];
         uint16_t width = current->sps_pic_width_max_in_luma_samples / sub_width_c;
         uint16_t height = current->sps_pic_height_max_in_luma_samples / sub_height_c;
         ue(sps_conf_win_left_offset, 0, width);
@@ -1160,19 +1161,37 @@  static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
             }
             for (i = 1; i <= current->sps_num_subpics_minus1; i++) {
                 if (!current->sps_subpic_same_size_flag) {
-                    if (current->sps_pic_width_max_in_luma_samples > ctb_size_y)
-                        ubs(wlen, sps_subpic_ctu_top_left_x[i], 1, i);
-                    else
+                    if (current->sps_pic_width_max_in_luma_samples > ctb_size_y) {
+                        const unsigned int win_right_edge =
+                            current->sps_pic_width_max_in_luma_samples
+                          - current->sps_conf_win_right_offset * sub_width_c;
+                        us(wlen, sps_subpic_ctu_top_left_x[i], 0,
+                           AV_CEIL_RSHIFT(win_right_edge, ctb_log2_size_y) - 1,
+                           1, i);
+                    } else
                         infer(sps_subpic_ctu_top_left_x[i], 0);
                     if (current->sps_pic_height_max_in_luma_samples >
-                        ctb_size_y)
-                        ubs(hlen, sps_subpic_ctu_top_left_y[i], 1, i);
-                    else
+                        ctb_size_y) {
+                        const unsigned int win_bottom_edge =
+                            current->sps_pic_height_max_in_luma_samples
+                          - current->sps_conf_win_bottom_offset * sub_height_c;
+                        us(hlen, sps_subpic_ctu_top_left_y[i], 0,
+                           AV_CEIL_RSHIFT(win_bottom_edge, ctb_log2_size_y) - 1,
+                           1, i);
+                    } else
                         infer(sps_subpic_ctu_top_left_y[i], 0);
                     if (i < current->sps_num_subpics_minus1 &&
                         current->sps_pic_width_max_in_luma_samples >
                         ctb_size_y) {
-                        ubs(wlen, sps_subpic_width_minus1[i], 1, i);
+                        const unsigned int win_left_edge =
+                            current->sps_conf_win_left_offset * sub_width_c;
+                        const unsigned int win_left_edge_ctus =
+                            AV_CEIL_RSHIFT(win_left_edge, ctb_log2_size_y);
+                        us(wlen, sps_subpic_width_minus1[i],
+                           win_left_edge_ctus > current->sps_subpic_ctu_top_left_x[i]
+                               ? win_left_edge_ctus - current->sps_subpic_ctu_top_left_x[i]
+                               : 0,
+                           MAX_UINT_BITS(wlen), 1, i);
                     } else {
                         infer(sps_subpic_width_minus1[i],
                               tmp_width_val -
@@ -1181,7 +1200,15 @@  static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
                     if (i < current->sps_num_subpics_minus1 &&
                         current->sps_pic_height_max_in_luma_samples >
                         ctb_size_y) {
-                        ubs(hlen, sps_subpic_height_minus1[i], 1, i);
+                        const unsigned int win_top_edge =
+                            current->sps_conf_win_top_offset * sub_height_c;
+                        const unsigned int win_top_edge_ctus =
+                            AV_CEIL_RSHIFT(win_top_edge, ctb_log2_size_y);
+                        us(hlen, sps_subpic_height_minus1[i],
+                           win_top_edge_ctus > current->sps_subpic_ctu_top_left_y[i]
+                               ? win_top_edge_ctus - current->sps_subpic_ctu_top_left_y[i]
+                               : 0,
+                           MAX_UINT_BITS(wlen), 1, i);
                     } else {
                         infer(sps_subpic_height_minus1[i],
                               tmp_height_val -