Prhub

#28153 fix(sampling): reject non-finite temperature in SamplingParams.verify

原始 PR 作者 Sunt-ing 合并时间 2026-06-14 14:41 文件变更 2 提交数 1 评论 2 代码增减 +15 / -2

执行摘要

修复非有限温度导致服务拒绝访问漏洞

PR body 指出,一个带有 NaN 或 +/-Inf 的 temperature 参数会导致整个服务器崩溃,这是一个请求级拒绝服务漏洞。由于 temperature 是通过 JSON 公开的参数,任何客户端都可以触发该漏洞。

值得精读,因为它展示了一个容易被忽视的安全漏洞(IEEE-754 特性导致单侧比较失效)以及简单的修复方法。代码改动极小但影响安全,适合作为输入验证的最佳实践示例。

讨论亮点

作者在 issue 评论中补充了与 vLLM 的对比分析,指出 vLLM 同样存在该验证漏洞,但由于其采样器内部处理了非有限概率值而未崩溃。这进一步强调了在验证层防御的重要性。无其他讨论。

实现拆解

  1. 修改验证逻辑python/sglang/srt/sampling/sampling_params.py):在 SamplingParams.verify() 方法中,将原有的单侧比较 if self.temperature < 0.0 改为 if not math.isfinite(self.temperature) or self.temperature < 0.0,并相应地更新错误消息。
  2. 更新导入python/sglang/srt/sampling/sampling_params.py):新增 import math
  3. 添加回归测试test/registered/unit/sampling/test_sampling_params.py):在 TestSamplingParamsVerify 类中添加两个测试用例 test_nan_temperature_raisestest_inf_temperature_raises,确保 NaN 和 Inf 温度被正确拒绝。
文件 模块 状态 重要度
python/sglang/srt/sampling/sampling_params.py 采样参数 modified 5.99
test/registered/unit/sampling/test_sampling_params.py 采样参数 modified 5.35

关键符号

verify

关键源码片段

python/sglang/srt/sampling/sampling_params.py core-logic

包含核心验证逻辑的修改,通过增加 isfinite 检查来拒绝非有限温度值。

# python/sglang/srt/sampling/sampling_params.py
import math # 新增导入class SamplingParams:
    # ... __init__ 代码保持不变 ...
​
    def verify(self, vocab_size):
        # 修复:原条件 self.temperature < 0.0 无法捕获 NaN/Inf(因为 nan < 0 为 False),
        # 新增 math.isfinite() 检查,确保温度是有限非负值。
        if not math.isfinite(self.temperature) or self.temperature < 0.0:
            raise ValueError(
                f"temperature must be a non-negative finite number, got {self.temperature}."
            )
        # 以下其他字段的验证保持不变
        if not 0.0 < self.top_p <= 1.0:
            raise ValueError(f"top_p must be in (0, 1], got {self.top_p}.")
        # ...
test/registered/unit/sampling/test_sampling_params.py test-coverage

添加了两个验证非有限温度值的回归测试用例,确保修复被正确覆盖。

# test/registered/unit/sampling/test_sampling_params.py
class TestSamplingParamsVerify(CustomTestCase):
    VOCAB_SIZE = 32000
​
    def _make(self, **kwargs):
        defaults = dict(temperature=1.0, top_p=1.0, top_k=10, min_p=0.0)
        defaults.update(kwargs)
        return SamplingParams(**defaults)
​
    def test_negative_temperature_raises(self):
        sp = self._make(temperature=-0.5)
        with self.assertRaises(ValueError):
            sp.verify(self.VOCAB_SIZE)
​
    # 新增:验证 NaN 温度被拒绝
    def test_nan_temperature_raises(self):
        """verify() must reject NaN temperature; the bare < 0.0 check alone lets it through."""
        sp = self._make(temperature=float("nan"))
        with self.assertRaises(ValueError):
            sp.verify(self.VOCAB_SIZE)
​
    # 新增:验证 Inf 温度被拒绝
    def test_inf_temperature_raises(self):
        """verify() must reject non-finite (inf) temperature."""
        sp = self._make(temperature=float("inf"))
        with self.assertRaises(ValueError):
            sp.verify(self.VOCAB_SIZE)

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

变更极小且仅在验证逻辑中,无回归风险。错误消息更新不影响兼容性。添加的测试覆盖了两个典型非有限情况,确保验证生效。

修复了请求级拒绝服务漏洞,防止恶意用户通过发送非有限温度值导致整个 SGLang 服务器崩溃。影响范围包括 /generate/v1/chat/completions/v1/completions 等所有接受 temperature 参数的端点。对正常用户无影响。

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论