This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:
Subject: edid-decode: Add sanity checks for DisplayID data blocks Author: yassha <[email protected]> Date: Wed Jan 7 22:06:27 2026 +0100 Add validation checks for DisplayID blocks (Tags 0x20, 0x21, 0x22, 0x24, 0x25) to ensure data integrity according to the VESA DisplayID Standard Version 2.1a: - Tag 0x20 (Product ID): Validate payload length, week range, and model year - Tag 0x21 (Display Parameters v2): Validate pixel format, chromaticity coordinates, luminance information, and gamma EOTF range - Tag 0x22 (Type VII Timing): Validate pixel clock max, image dimensions max - Tag 0x24 (Type IX Timing): Validate image dimensions max and refresh rate max - Tag 0x25 (Dynamic Video Timing Range Limits): Validate pixel clock and refresh rate ranges with revision-specific limits Signed-off-by: yassha <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> [hverkuil: drop duplicate check for negative blanking] utils/edid-decode/parse-displayid-block.cpp | 124 +++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 22 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=544e1df2cff7d1d058f12130655f1384cdd58cf3 diff --git a/utils/edid-decode/parse-displayid-block.cpp b/utils/edid-decode/parse-displayid-block.cpp index 23f1a69b236b..2fa8fde7418e 100644 --- a/utils/edid-decode/parse-displayid-block.cpp +++ b/utils/edid-decode/parse-displayid-block.cpp @@ -107,6 +107,14 @@ void edid_state::parse_displayid_product_id(const unsigned char *x) buf[x[14]] = 0; printf(" Product ID: %s\n", buf); } + + unsigned len = x[2]; + if (len < 12) + fail("Product Identification payload length (%u) is less than minimum required (12 bytes).\n", len); + if (week != 0 && week != 0xff && (week < 1 || week > 52)) + fail("Week of Manufacture/Model Tag (%u) is out of valid range (0, 1-52, or 0xFF).\n", week); + if (week == 0xff && x[13] < 0x0f) + fail("Model Year specified (Week=0xFF) but Year value (%u) is in RESERVED range (0x00-0x0E).\n", x[13]); } // tag 0x01 @@ -387,6 +395,11 @@ void edid_state::parse_displayid_type_1_7_timing(const unsigned char *x, if (match_timings(t, cvt_t)) fail("This T7VTDB can be represented as a T10VTDB.\n"); } + + if (t.pixclk_khz > 16777216) + fail("Pixel Clock (%.3f MP/s) exceeds maximum (16,777.216 MP/s).\n", t.pixclk_khz / 1000.0); + if (t.hact > 65536 || t.vact > 65536) + fail("Active image dimensions exceed maximum (65536): %ux%u.\n", t.hact, t.vact); } // tag 0x04 @@ -1236,31 +1249,56 @@ void edid_state::parse_displayid_parameters_v2(const unsigned char *x, switch ((v >> 3) & 0x03) { case 0x00: printf("Minimum guaranteed value\n"); break; case 0x01: printf("Guidance for the Source device\n"); break; - default: printf("Reserved\n"); break; + default: + printf("Reserved\n"); + fail("Luminance Information field uses reserved value (%u).\n", (v >> 3) & 0x03); + break; } printf(" Color Information: CIE %u\n", (v & 0x40) ? 1976 : 1931); printf(" Audio Speaker Information: %sintegrated\n", (v & 0x80) ? "not " : ""); + + double prim1_x = fp2d(x[0x0c] | ((x[0x0d] & 0x0f) << 8)); + double prim1_y = fp2d(((x[0x0d] & 0xf0) >> 4) | (x[0x0e] << 4)); + double prim2_x = fp2d(x[0x0f] | ((x[0x10] & 0x0f) << 8)); + double prim2_y = fp2d(((x[0x10] & 0xf0) >> 4) | (x[0x11] << 4)); + double prim3_x = fp2d(x[0x12] | ((x[0x13] & 0x0f) << 8)); + double prim3_y = fp2d(((x[0x13] & 0xf0) >> 4) | (x[0x14] << 4)); + double white_x = fp2d(x[0x15] | ((x[0x16] & 0x0f) << 8)); + double white_y = fp2d(((x[0x16] & 0xf0) >> 4) | (x[0x17] << 4)); + printf(" Native Color Chromaticity:\n"); - printf(" Primary #1: (%.6f, %.6f)\n", - fp2d(x[0x0c] | ((x[0x0d] & 0x0f) << 8)), - fp2d(((x[0x0d] & 0xf0) >> 4) | (x[0x0e] << 4))); - printf(" Primary #2: (%.6f, %.6f)\n", - fp2d(x[0x0f] | ((x[0x10] & 0x0f) << 8)), - fp2d(((x[0x10] & 0xf0) >> 4) | (x[0x11] << 4))); - printf(" Primary #3: (%.6f, %.6f)\n", - fp2d(x[0x12] | ((x[0x13] & 0x0f) << 8)), - fp2d(((x[0x13] & 0xf0) >> 4) | (x[0x14] << 4))); - printf(" White Point: (%.6f, %.6f)\n", - fp2d(x[0x15] | ((x[0x16] & 0x0f) << 8)), - fp2d(((x[0x16] & 0xf0) >> 4) | (x[0x17] << 4))); + printf(" Primary #1: (%.6f, %.6f)\n", prim1_x, prim1_y); + printf(" Primary #2: (%.6f, %.6f)\n", prim2_x, prim2_y); + printf(" Primary #3: (%.6f, %.6f)\n", prim3_x, prim3_y); + printf(" White Point: (%.6f, %.6f)\n", white_x, white_y); + + if (prim1_x < 0.0 || prim1_x > 1.0 || prim1_y < 0.0 || prim1_y > 1.0 || + prim2_x < 0.0 || prim2_x > 1.0 || prim2_y < 0.0 || prim2_y > 1.0 || + prim3_x < 0.0 || prim3_x > 1.0 || prim3_y < 0.0 || prim3_y > 1.0 || + white_x < 0.0 || white_x > 1.0 || white_y < 0.0 || white_y > 1.0) { + fail("Chromaticity coordinates are out of valid range (0.0-1.0).\n"); + } + printf(" Native Maximum Luminance (Full Coverage): %s\n", ieee7542d(x[0x18] | (x[0x19] << 8)).c_str()); printf(" Native Maximum Luminance (10%% Rectangular Coverage): %s\n", ieee7542d(x[0x1a] | (x[0x1b] << 8)).c_str()); printf(" Native Minimum Luminance: %s\n", ieee7542d(x[0x1c] | (x[0x1d] << 8)).c_str()); + + if ((x[0x18] | (x[0x19] << 8)) == 0x8000) { + if ((v >> 3) & 0x03) { + fail("Luminance Information field should be 0 when Maximum Luminance (Full Coverage) is -0.\n"); + } + } + if ((x[0x1a] | (x[0x1b] << 8)) == 0x8000) { + if ((v >> 3) & 0x03) { + fail("Luminance Information field should be 0 when Maximum Luminance (10%%) is -0.\n"); + } + } + printf(" Native Color Depth: "); if (!(x[0x1e] & 0x07)) printf("Not defined\n"); @@ -1281,6 +1319,16 @@ void edid_state::parse_displayid_parameters_v2(const unsigned char *x, if (x[0x1f] != 0xff) printf(" Native Gamma EOTF: %.2f\n", (100 + x[0x1f]) / 100.0); + + if ((w == 0) != (h == 0)) + fail("Invalid Native Pixel Format: one dimension is zero while the other is not (%ux%u).\n", w, h); + if (w > 65535 || h > 65535) + fail("Native Pixel Format exceeds maximum value (%ux%u > 65535x65535).\n", w, h); + if (x[0x1f] != 0xff) { + double gamma = (100 + x[0x1f]) / 100.0; + if (gamma < 1.00 || gamma > 3.754) + fail("Native Gamma EOTF (%.2f) is out of valid range (1.00-3.754).\n", gamma); + } } // tag 0x24 @@ -1323,6 +1371,11 @@ void edid_state::parse_displayid_type_9_timing(const unsigned char *x) edid_cvt_mode(1 + x[5], t); print_timings(" ", &t, "CVT", s.c_str()); + + if (t.hact > 65536 || t.vact > 65536) + fail("Type IX active image dimensions exceed maximum (65536): %ux%u.\n", t.hact, t.vact); + if (1 + x[5] > 256) + fail("Type IX refresh rate (%u Hz) exceeds maximum (256 Hz).\n", 1 + x[5]); } // tag 0x25 @@ -1334,17 +1387,44 @@ void edid_state::parse_displayid_dynamic_video_timings_range_limits(const unsign if (!check_displayid_datablock_length(x, 9, 9)) return; - printf(" Minimum Pixel Clock: %u kHz\n", - 1 + (x[3] | (x[4] << 8) | (x[5] << 16))); - printf(" Maximum Pixel Clock: %u kHz\n", - 1 + (x[6] | (x[7] << 8) | (x[8] << 16))); - printf(" Minimum Vertical Refresh Rate: %u Hz\n", x[9]); - if (x[1] & 7) - printf(" Maximum Vertical Refresh Rate: %u Hz\n", x[10] + ((x[11] & 3) << 8)); - else - printf(" Maximum Vertical Refresh Rate: %u Hz\n", x[10]); + unsigned min_pixclk = 1 + (x[3] | (x[4] << 8) | (x[5] << 16)); + unsigned max_pixclk = 1 + (x[6] | (x[7] << 8) | (x[8] << 16)); + unsigned min_refresh = x[9]; + unsigned max_refresh; + + printf(" Minimum Pixel Clock: %u kHz\n", min_pixclk); + printf(" Maximum Pixel Clock: %u kHz\n", max_pixclk); + printf(" Minimum Vertical Refresh Rate: %u Hz\n", min_refresh); + + if (x[1] & 7) { + max_refresh = x[10] + ((x[11] & 3) << 8); + printf(" Maximum Vertical Refresh Rate: %u Hz\n", max_refresh); + if (max_refresh > 1023) { + fail("Maximum Vertical Refresh Rate (%u Hz) exceeds maximum (1023 Hz).\n", max_refresh); + } + } else { + max_refresh = x[10]; + printf(" Maximum Vertical Refresh Rate: %u Hz\n", max_refresh); + if (max_refresh > 255) { + fail("Maximum Vertical Refresh Rate (%u Hz) exceeds maximum (255 Hz for Revision 0).\n", max_refresh); + } + } + printf(" Seamless Dynamic Video Timing Support: %s\n", (x[11] & 0x80) ? "Yes" : "No"); + + if (min_pixclk > max_pixclk) { + fail("Minimum Pixel Clock (%u kHz) is greater than Maximum Pixel Clock (%u kHz).\n", + min_pixclk, max_pixclk); + } + if (max_pixclk > 16777216) { + fail("Maximum Pixel Clock (%u kHz = %.3f MP/s) exceeds maximum (16,777.216 MP/s).\n", + max_pixclk, max_pixclk / 1000.0); + } + if (min_refresh > max_refresh) { + fail("Minimum Vertical Refresh Rate (%u Hz) is greater than Maximum Vertical Refresh Rate (%u Hz).\n", + min_refresh, max_refresh); + } } // tag 0x26 _______________________________________________ linuxtv-commits mailing list -- [email protected] To unsubscribe send an email to [email protected]
