nvidia-modeset: fix UB in DP DSC flatnessDetThresh calculation#1052
Open
edenfunf wants to merge 1 commit intoNVIDIA:mainfrom
Open
nvidia-modeset: fix UB in DP DSC flatnessDetThresh calculation#1052edenfunf wants to merge 1 commit intoNVIDIA:mainfrom
edenfunf wants to merge 1 commit intoNVIDIA:mainfrom
Conversation
…lculation
EvoSetDpDscParams() and EvoSetDpDscParamsC9() compute the DSC flatness
detection threshold using bitsPerPixelX16 instead of bits_per_component.
bitsPerPixelX16 is BPP * 16 (e.g. 128 for 8.0 bpp), so the expression
2 << (bitsPerPixelX16 - 8) produces a shift of 120+ bits, which is
undefined behavior in C. The resulting garbage value is written to the
FLATNESS_DET_THRESH hardware register field (10-bit).
The HDMI DSC path already handles this correctly by deriving bpc from
the pixelDepth parameter, but the DP path does not receive pixelDepth.
Instead, extract bits_per_component from PPS byte 3 bits [7:4], which
the DP library has already computed correctly.
Introduce two shared helpers:
- nvDscPpsGetBitsPerComponent(): extract bpc from PPS DWord 0
- nvDscComputeFlatnessDetThresh(): compute 2 << (bpc - 8) with
validation and clamping for bpc < 8
Both DP and HDMI DSC paths now use nvDscComputeFlatnessDetThresh(),
eliminating the duplicated inline validation in the HDMI path and
ensuring consistent behavior across all display class versions.
Fixes: VESA DSC 1.2a section 4.1 flatness_det_thresh formula
Closes: NVIDIA#1029
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
EvoSetDpDscParams()(nvkms-evo3.c) andEvoSetDpDscParamsC9()(nvkms-evo4.c) compute the DSC flatness detection threshold as:bitsPerPixelX16is the target bits-per-pixel multiplied by 16 (e.g. 128 for 8.0 bpp, 384 for 24.0 bpp). This produces a left shift of 120–376 bits, which is undefined behavior in C — the shift amount far exceeds the width ofNvU32. The hardware register fieldFLATNESS_DET_THRESHis only 10 bits wide, so whatever garbage value results from the UB gets truncated and programmed into the DSC encoder.The existing code even has an engineer comment acknowledging this:
The HDMI DSC path (
EvoSetHdmiDscParams/EvoSetHdmiDscParamsC9) handles this correctly by derivingbpcfrom thepixelDepthparameter and computing2 << (bpc - 8). However, the DP path does not receive apixelDepthparameter.Fix
Per VESA DSC 1.2a section 4.1, the correct formula is:
Since the DP path doesn't have
pixelDepth, we extractbits_per_componentdirectly from PPS byte 3 bits [7:4], which the DP library has already computed when generating the PPS.This patch introduces two shared utility functions:
nvDscPpsGetBitsPerComponent()— extracts bpc from PPS DWord 0 bits [31:28]nvDscComputeFlatnessDetThresh()— computes2 << (bpc - 8)with validation/clamping for safetyBoth the DP and HDMI paths now use
nvDscComputeFlatnessDetThresh(), consolidating the duplicated inline validation that previously existed only in the HDMI path.Impact
Affects all DisplayPort DSC displays on all GPU generations supported by the open kernel modules. The flatness detection threshold controls how the DSC encoder identifies flat (uniform) image regions for optimized bit allocation. An incorrect threshold may cause suboptimal compression and potential visual artifacts.
Files Changed
src/nvidia-modeset/include/nvkms-utils.h— declare new helperssrc/nvidia-modeset/src/nvkms-utils.c— implementnvDscPpsGetBitsPerComponent()andnvDscComputeFlatnessDetThresh()src/nvidia-modeset/src/nvkms-evo3.c— fixEvoSetDpDscParams(), refactorEvoSetHdmiDscParams()src/nvidia-modeset/src/nvkms-evo4.c— fixEvoSetDpDscParamsC9(), refactorEvoSetHdmiDscParamsC9()Closes #1029