DF-4731 / df4731_proof.c
/* * DF-4731 proof-of-logic harness (userland, no GPU required). * * Extracts verbatim: * - enum dc_irq_source (sys/dev/drm/amd/display/dc/irq_types.h:40-148) * - DAL_VALID_IRQ_SRC_NUM (sys/dev/drm/amd/display/dc/irq_types.h:157-158) * * Demonstrates that DAL_VALID_IRQ_SRC_NUM(DAL_IRQ_SOURCES_NUMBER) == true, * i.e. amdgpu_dm_irq.c's validate_irq_registration_params() * (sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c:176) accepts * irq_source == DAL_IRQ_SOURCES_NUMBER, which amdgpu_dm_irq_register_interrupt() * then uses to index: * adev->dm.irq_handler_list_high_tab[irq_source] (amdgpu_dm_irq.c:238) * adev->dm.irq_handler_list_low_tab[irq_source].head (amdgpu_dm_irq.c:242) * arrays declared as [DAL_IRQ_SOURCES_NUMBER] (amdgpu_dm.h:106-107) * -> one-past-the-end struct access. * * Build: cc -O2 -o df4731_proof df4731_proof.c * Run: ./df4731_proof */ #include <stdio.h> #include <stdbool.h> /* ---- verbatim from sys/dev/drm/amd/display/dc/irq_types.h ---- */ enum dc_irq_source { DC_IRQ_SOURCE_INVALID = 0, DC_IRQ_SOURCE_HPD1, DC_IRQ_SOURCE_HPD2, DC_IRQ_SOURCE_HPD3, DC_IRQ_SOURCE_HPD4, DC_IRQ_SOURCE_HPD5, DC_IRQ_SOURCE_HPD6, DC_IRQ_SOURCE_HPD1RX, DC_IRQ_SOURCE_HPD2RX, DC_IRQ_SOURCE_HPD3RX, DC_IRQ_SOURCE_HPD4RX, DC_IRQ_SOURCE_HPD5RX, DC_IRQ_SOURCE_HPD6RX, DC_IRQ_SOURCE_I2C_DDC1, DC_IRQ_SOURCE_I2C_DDC2, DC_IRQ_SOURCE_I2C_DDC3, DC_IRQ_SOURCE_I2C_DDC4, DC_IRQ_SOURCE_I2C_DDC5, DC_IRQ_SOURCE_I2C_DDC6, DC_IRQ_SOURCE_DPSINK1, DC_IRQ_SOURCE_DPSINK2, DC_IRQ_SOURCE_DPSINK3, DC_IRQ_SOURCE_DPSINK4, DC_IRQ_SOURCE_DPSINK5, DC_IRQ_SOURCE_DPSINK6, DC_IRQ_SOURCE_TIMER, DC_IRQ_SOURCE_PFLIP_FIRST, DC_IRQ_SOURCE_PFLIP1 = DC_IRQ_SOURCE_PFLIP_FIRST, DC_IRQ_SOURCE_PFLIP2, DC_IRQ_SOURCE_PFLIP3, DC_IRQ_SOURCE_PFLIP4, DC_IRQ_SOURCE_PFLIP5, DC_IRQ_SOURCE_PFLIP6, DC_IRQ_SOURCE_PFLIP_UNDERLAY0, DC_IRQ_SOURCE_PFLIP_LAST = DC_IRQ_SOURCE_PFLIP_UNDERLAY0, DC_IRQ_SOURCE_GPIOPAD0, DC_IRQ_SOURCE_GPIOPAD1, DC_IRQ_SOURCE_GPIOPAD2, DC_IRQ_SOURCE_GPIOPAD3, DC_IRQ_SOURCE_GPIOPAD4, DC_IRQ_SOURCE_GPIOPAD5, DC_IRQ_SOURCE_GPIOPAD6, DC_IRQ_SOURCE_GPIOPAD7, DC_IRQ_SOURCE_GPIOPAD8, DC_IRQ_SOURCE_GPIOPAD9, DC_IRQ_SOURCE_GPIOPAD10, DC_IRQ_SOURCE_GPIOPAD11, DC_IRQ_SOURCE_GPIOPAD12, DC_IRQ_SOURCE_GPIOPAD13, DC_IRQ_SOURCE_GPIOPAD14, DC_IRQ_SOURCE_GPIOPAD15, DC_IRQ_SOURCE_GPIOPAD16, DC_IRQ_SOURCE_GPIOPAD17, DC_IRQ_SOURCE_GPIOPAD18, DC_IRQ_SOURCE_GPIOPAD19, DC_IRQ_SOURCE_GPIOPAD20, DC_IRQ_SOURCE_GPIOPAD21, DC_IRQ_SOURCE_GPIOPAD22, DC_IRQ_SOURCE_GPIOPAD23, DC_IRQ_SOURCE_GPIOPAD24, DC_IRQ_SOURCE_GPIOPAD25, DC_IRQ_SOURCE_GPIOPAD26, DC_IRQ_SOURCE_GPIOPAD27, DC_IRQ_SOURCE_GPIOPAD28, DC_IRQ_SOURCE_GPIOPAD29, DC_IRQ_SOURCE_GPIOPAD30, DC_IRQ_SOURCE_DC1UNDERFLOW, DC_IRQ_SOURCE_DC2UNDERFLOW, DC_IRQ_SOURCE_DC3UNDERFLOW, DC_IRQ_SOURCE_DC4UNDERFLOW, DC_IRQ_SOURCE_DC5UNDERFLOW, DC_IRQ_SOURCE_DC6UNDERFLOW, DC_IRQ_SOURCE_DMCU_SCP, DC_IRQ_SOURCE_VBIOS_SW, DC_IRQ_SOURCE_VUPDATE1, DC_IRQ_SOURCE_VUPDATE2, DC_IRQ_SOURCE_VUPDATE3, DC_IRQ_SOURCE_VUPDATE4, DC_IRQ_SOURCE_VUPDATE5, DC_IRQ_SOURCE_VUPDATE6, DC_IRQ_SOURCE_VBLANK1, DC_IRQ_SOURCE_VBLANK2, DC_IRQ_SOURCE_VBLANK3, DC_IRQ_SOURCE_VBLANK4, DC_IRQ_SOURCE_VBLANK5, DC_IRQ_SOURCE_VBLANK6, DC_IRQ_SOURCE_DC1_VLINE0, DC_IRQ_SOURCE_DC2_VLINE0, DC_IRQ_SOURCE_DC3_VLINE0, DC_IRQ_SOURCE_DC4_VLINE0, DC_IRQ_SOURCE_DC5_VLINE0, DC_IRQ_SOURCE_DC6_VLINE0, DAL_IRQ_SOURCES_NUMBER }; #define DAL_VALID_IRQ_SRC_NUM(src) \ ((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) /* ---- end verbatim ---- */ int main(void) { bool accept_last_valid = DAL_VALID_IRQ_SRC_NUM(DAL_IRQ_SOURCES_NUMBER - 1); bool accept_one_past = DAL_VALID_IRQ_SRC_NUM(DAL_IRQ_SOURCES_NUMBER); bool accept_two_past = DAL_VALID_IRQ_SRC_NUM(DAL_IRQ_SOURCES_NUMBER + 1); bool accept_invalid = DAL_VALID_IRQ_SRC_NUM(DC_IRQ_SOURCE_INVALID); printf("enum size : DAL_IRQ_SOURCES_NUMBER = %d\n", DAL_IRQ_SOURCES_NUMBER); printf("array extent : irq_handler_list_{low,high}_tab[%d] -> valid idx 0..%d\n", DAL_IRQ_SOURCES_NUMBER, DAL_IRQ_SOURCES_NUMBER - 1); printf("accept src=%-3d (last valid) : %s\n", DAL_IRQ_SOURCES_NUMBER - 1, accept_last_valid ? "true (correct)" : "false"); printf("accept src=%-3d (ONE PAST) : %s <-- BUG: feeds tab[90] in\n", DAL_IRQ_SOURCES_NUMBER, accept_one_past ? "true" : "false"); printf(" amdgpu_dm_irq.c:238/:242/:123/:127 (list_add_tail/list walk)\n"); printf("accept src=%-3d (two past) : %s\n", DAL_IRQ_SOURCES_NUMBER + 1, accept_two_past ? "true" : "false"); printf("accept src=%-3d (INVALID) : %s (correct)\n", DC_IRQ_SOURCE_INVALID, accept_invalid ? "true" : "false"); if (accept_one_past && !accept_two_past && accept_last_valid) { printf("\nRESULT: OFF-BY-ONE CONFIRMED - exactly index == array size passes\n"); printf(" the guard used by validate_irq_registration_params()\n"); printf(" and validate_irq_unregistration_params().\n"); return 0; } printf("\nRESULT: guard behaved unexpectedly\n"); return 1; } |