[Mesa-dev] [PATCH] intel/isl: Tighten up format info lookup
Jason Ekstrand
jason at jlekstrand.net
Mon Jun 5 16:28:22 UTC 2017
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
More information about the mesa-dev
mailing list