The old code would just blindly dereference arrays with no protection whatsoever. This is a problem because the format_info array is too short to contain ISL_FORMAT_UNSUPPORTED or any of the aux formats. This can lead to segfaults when the array is dereferenced. This commit switches everything over to using a helper for getting isl_format_info which does some useful asserting. While we're here, we add the same asserts to isl_format_get_layout(). --- src/intel/isl/isl.h | 8 ++++++ src/intel/isl/isl_format.c | 62 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h index 658f67e..5f9baa7 100644 --- a/src/intel/isl/isl.h +++ b/src/intel/isl/isl.h @@ -389,6 +389,11 @@ enum isl_format { ISL_FORMAT_GEN9_CCS_64BPP, ISL_FORMAT_GEN9_CCS_128BPP, + /* This way we can easily tell if it's a valid format. Note: + * ISL_FORMAT_UNSUPPORTED is not considered valid. + */ + ISL_FORMAT_MAX_VALID_ENUM, + /* Hardware doesn't understand this out-of-band value */ ISL_FORMAT_UNSUPPORTED = UINT16_MAX, }; @@ -1170,6 +1175,9 @@ isl_device_get_sample_counts(struct isl_device *dev); static inline const struct isl_format_layout * ATTRIBUTE_CONST isl_format_get_layout(enum isl_format fmt) { + assert(fmt != ISL_FORMAT_UNSUPPORTED); + assert(fmt < ISL_FORMAT_MAX_VALID_ENUM); + return &isl_format_layouts[fmt]; } diff --git a/src/intel/isl/isl_format.c b/src/intel/isl/isl_format.c index e6d2a43..02e09e9 100644 --- a/src/intel/isl/isl_format.c +++ b/src/intel/isl/isl_format.c @@ -21,12 +21,13 @@ * IN THE SOFTWARE. */ +#include <stdlib.h> #include <assert.h> #include "isl.h" #include "common/gen_device_info.h" -struct surface_format_info { +struct isl_format_info { bool exists; uint8_t sampling; uint8_t filtering; @@ -87,7 +88,7 @@ struct surface_format_info { * - VOL4_Part1 section 3.9.11 Render Target Write. * - Render Target Surface Types [SKL+] */ -static const struct surface_format_info format_info[] = { +static const struct isl_format_info format_infos[] = { /* smpl filt shad CK RT AB VB SO color TW TR ccs_e */ SF( Y, 50, x, x, Y, Y, Y, Y, x, 70, 90, 90, R32G32B32A32_FLOAT) SF( Y, x, x, x, Y, x, Y, Y, x, 70, 90, 90, R32G32B32A32_SINT) @@ -359,6 +360,21 @@ static const struct surface_format_info format_info[] = { #undef x #undef Y +static inline const struct isl_format_info * +isl_format_get_info(enum isl_format format) +{ + assert(format != ISL_FORMAT_UNSUPPORTED); + assert(format < ISL_FORMAT_MAX_VALID_ENUM); + + if (format >= ARRAY_SIZE(format_infos)) + return NULL; + + if (!format_infos[format].exists) + return NULL; + + return &format_infos[format]; +} + static unsigned format_gen(const struct gen_device_info *devinfo) { @@ -369,27 +385,30 @@ bool isl_format_supports_rendering(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; - return format_gen(devinfo) >= format_info[format].render_target; + return format_gen(devinfo) >= info->render_target; } bool isl_format_supports_alpha_blending(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; - return format_gen(devinfo) >= format_info[format].alpha_blend; + return format_gen(devinfo) >= info->alpha_blend; } bool isl_format_supports_sampling(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; if (devinfo->is_baytrail) { @@ -415,14 +434,15 @@ isl_format_supports_sampling(const struct gen_device_info *devinfo, return true; } - return format_gen(devinfo) >= format_info[format].sampling; + return format_gen(devinfo) >= info->sampling; } bool isl_format_supports_filtering(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; if (devinfo->is_baytrail) { @@ -448,23 +468,24 @@ isl_format_supports_filtering(const struct gen_device_info *devinfo, return true; } - return format_gen(devinfo) >= format_info[format].filtering; + return format_gen(devinfo) >= info->filtering; } bool isl_format_supports_vertex_fetch(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; /* For vertex fetch, Bay Trail supports the same set of formats as Haswell * but is a superset of Ivy Bridge. */ if (devinfo->is_baytrail) - return 75 >= format_info[format].input_vb; + return 75 >= info->input_vb; - return format_gen(devinfo) >= format_info[format].input_vb; + return format_gen(devinfo) >= info->input_vb; } /** @@ -474,10 +495,11 @@ bool isl_format_supports_typed_writes(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; - return format_gen(devinfo) >= format_info[format].typed_write; + return format_gen(devinfo) >= info->typed_write; } @@ -495,10 +517,11 @@ bool isl_format_supports_typed_reads(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; - return format_gen(devinfo) >= format_info[format].typed_read; + return format_gen(devinfo) >= info->typed_read; } /** @@ -533,10 +556,11 @@ bool isl_format_supports_ccs_e(const struct gen_device_info *devinfo, enum isl_format format) { - if (!format_info[format].exists) + const struct isl_format_info *info = isl_format_get_info(format); + if (info == NULL) return false; - return format_gen(devinfo) >= format_info[format].ccs_e; + return format_gen(devinfo) >= info->ccs_e; } bool -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev