[x264-devel] [PATCH] Fix index out-of-bound bugs
BugMaster
BugMaster at narod.ru
Wed Apr 1 07:56:26 CEST 2020
On Tue, 31 Mar 2020 17:12:53 -0700, Vitaly Buka wrote:
> From: Vitaly Buka <vitalybuka at gmail.com>
> 1. i_mb_partition does not match loop at encoder/encoder.c:4025
> It looks like it should have the same size as i_mb_count[3].
> 2. lowres_mvs[1][p1-b-1] is fix of "undefined behaviour"
> In some cases index is negative. There is no memory when it happens.
> However, according to the C standard even calculation of such pointer
> is undefined behaviour.
> https://port70.net/~nsz/c/c11/n1570.html#6.5.6p8
> Both were detected with clang -fsanitize=bounds and the fix will help
> to use this code in projects where -fsanitize=bounds is used.
> ---
> common/common.h | 2 +-
> encoder/slicetype.c | 7 ++++---
> 2 files changed, 5 insertions(+), 4 deletions(-)
> diff --git a/common/common.h b/common/common.h
> index a167df63..06f9144c 100644
> --- a/common/common.h
> +++ b/common/common.h
> @@ -697,7 +697,7 @@ struct x264_t
> double f_frame_duration[3];
> /* */
> int64_t i_mb_count[3][19];
> - int64_t i_mb_partition[2][17];
> + int64_t i_mb_partition[3][17];
> int64_t i_mb_count_8x8dct[2];
> int64_t i_mb_count_ref[2][2][X264_REF_MAX*2];
> int64_t i_mb_cbp[6];
> diff --git a/encoder/slicetype.c b/encoder/slicetype.c
> index a520f586..487727ee 100644
> --- a/encoder/slicetype.c
> +++ b/encoder/slicetype.c
> @@ -519,8 +519,6 @@ static void slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,
> const int i_stride = fenc->i_stride_lowres;
> const int i_pel_offset = 8 * (i_mb_x + i_mb_y * i_stride);
> const int i_bipred_weight = h->param.analyse.b_weighted_bipred
> ? 64 - (dist_scale_factor>>2) : 32;
> - int16_t (*fenc_mvs[2])[2] = {
> &fenc->lowres_mvs[0][b-p0-1][i_mb_xy],
> &fenc->lowres_mvs[1][p1-b-1][i_mb_xy] };
> - int (*fenc_costs[2]) = {
> &fenc->lowres_mv_costs[0][b-p0-1][i_mb_xy],
> &fenc->lowres_mv_costs[1][p1-b-1][i_mb_xy] };
> int b_frame_score_mb = (i_mb_x > 0 && i_mb_x < h->mb.i_mb_width - 1 &&
> i_mb_y > 0 && i_mb_y < h->mb.i_mb_height - 1) ||
> h->mb.i_mb_width <= 2 || h->mb.i_mb_height <= 2;
> @@ -539,6 +537,9 @@ static void slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,
> if( p0 == p1 )
> goto lowres_intra_mb;
>
> + int16_t (*fenc_mvs[2])[2] = {
> &fenc->lowres_mvs[0][b-p0-1][i_mb_xy], p1 == b ? NULL :
> &fenc->lowres_mvs[1][p1-b-1][i_mb_xy] };
> + int (*fenc_costs[2]) = {
> &fenc->lowres_mv_costs[0][b-p0-1][i_mb_xy], p1 == b ? NULL :
> &fenc->lowres_mv_costs[1][p1-b-1][i_mb_xy] };
> +
> int mv_range = 2 * h->param.analyse.i_mv_range;
> // no need for h->mb.mv_min[]
> h->mb.mv_min_spel[0] = X264_MAX( 4*(-8*h->mb.i_mb_x - 12), -mv_range );
> @@ -1045,7 +1046,7 @@ static void macroblock_tree_propagate( x264_t
> *h, x264_frame_t **frames, float a
> uint16_t *ref_costs[2] =
> {frames[p0]->i_propagate_cost,frames[p1]->i_propagate_cost};
> int dist_scale_factor = ( ((b-p0) << 8) + ((p1-p0) >> 1) ) / (p1-p0);
> int i_bipred_weight = h->param.analyse.b_weighted_bipred ? 64 - (dist_scale_factor>>2) : 32;
> - int16_t (*mvs[2])[2] = { frames[b]->lowres_mvs[0][b-p0-1],
> frames[b]->lowres_mvs[1][p1-b-1] };
> + int16_t (*mvs[2])[2] = { frames[b]->lowres_mvs[0][b-p0-1], b
> == p1 ? NULL : frames[b]->lowres_mvs[1][p1-b-1] };
> int bipred_weights[2] = {i_bipred_weight, 64 - i_bipred_weight};
> int16_t *buf = h->scratch_buffer;
> uint16_t *propagate_cost = frames[b]->i_propagate_cost;
Hi.
Thanks for the report but that is already fixed in my fork:
https://code.videolan.org/BugMaster/x264/-/commit/418788e79dbd10c6f37321bca1c4c4320e9a0ffa
Also some other undefined behaviour reported by clang also fixed in
that branch: https://code.videolan.org/BugMaster/x264/-/commits/devel
That will be pushed to official repo when I finish one more patch and
fix commit messages and make code review of all of them.
More information about the x264-devel
mailing list