深入分析图形渲染库精度问题引发的安全漏洞(下篇)
字数 1193 2025-08-20 18:17:48
图形渲染库精度问题引发的安全漏洞分析
概述
本文深入分析了图形渲染库中由于精度问题引发的安全漏洞,重点探讨了Skia和SwiftShader图形库中的精度误差问题。这些漏洞可能导致越界内存访问,进而引发安全风险。
浮点精度误差问题
样条线转换为线段时的浮点精度误差
在绘制路径时,Skia会将非线性曲线(圆锥曲线、二次和三次样条)转换为线段,这一转换过程容易受到浮点精度误差的影响。
三次样条转换过程
-
系数计算:
fA = P3 + three * (P1 - P2) - P0; fB = three * (P2 - times_2(P1) + P0); fC = three * (P1 - P0); fD = P0; -
线段点计算:
const Sk2s dt(SK_Scalar1 / lines); Sk2s t(0); Sk2s A = coeff.fA; Sk2s B = coeff.fB; Sk2s C = coeff.fC; Sk2s D = coeff.fD; for (int i = 1; i < lines; ++i) { t = t + dt; Sk2s p = ((A * t + B) * t + C) * t + D; p.store(&tmp[i]); }
精度误差示例
对于绘图区域宽度为1000像素的情况,考虑以下坐标:
p0 = 1.501923
p1 = 998.468811
p2 = 998.998779
p3 = 999.000000
计算得到的系数:
a = 995.908203
b = -2989.310547
c = 2990.900879
d = 1.501923
使用512个线段逼近时,部分x坐标结果:
511 : 999.000244 // 超出安全区域
更大绘图区域的影响
对于32767像素的绘图区域(Chrome最大画布尺寸),考虑以下点:
p0 = 1.7490234375
p1 = 32765.9902343750
p2 = 32766.000000
p3 = 32766.000000
部分逼近结果:
511 : 32766.015625 // 明显越界
缓解措施:SkDrawTiler将大于8191x8191像素的图像拆分为多个图块,有效限制了精度误差的影响范围。
整数精度误差问题
样条线转换为线段时的整数精度误差
在填充路径时,SkCubicEdge::setCubicWithoutUpdate中的定点运算可能出现精度误差。
关键计算过程
SkFixed B = SkFDot6UpShift(3 * (x1 - x0), upShift);
SkFixed C = SkFDot6UpShift(3 * (x0 - x1 - x1 + x2), upShift);
SkFixed D = SkFDot6UpShift(x3 + 3 * (x1 - x2) - x0, upShift);
fCx = SkFDot6ToFixed(x0);
fCDx = B + (C >> shift) + (D >> 2 * shift); // 问题所在
fCDDx = 2 * C + (3 * D >> (shift - 1));
fCDDDx = 3 * D >> (shift - 1);
精度误差示例
输入值:
x0 = -30
x1 = -31
x2 = -31
x3 = -31
计算参数:
B = -192
C = 192
D = -64
fCx = -30720
fCDx = -190 // 应为-189.015
线段逼近结果(部分):
35 : -0.484421 // 小于最小输入点-0.484375
...
64 : -0.488846
转换为SkFDot6类型后:
-31747 (SkFixed) >> 10 → -32 (SkFDot6, 即-0.5)
安全影响
-
内存访问模式:
- y=-1或y=height:堆越界写
- y=0且x=-1:堆下溢1像素
- x=width且y=height-1:堆溢出1像素
- y>0且x=-1:像素"溢出"到上一图像行
- x=height且y<height-1:像素"溢出"到下一图像行
-
SkARGB32_Shader_Blitter问题:
- 分配与单行图像大小相同的临时缓冲区
- 从x=-1到x=width-1渲染时,会写入width+1像素,导致缓冲区溢出
触发条件
- 必须使用SVG图像并设置
shape-rendering="crispEdges"来关闭抗锯齿 - 需要包含
linearGradient元素以选择SkARGB32_Shader_Blitter
修复方案
Skia通过增加kConservativeRoundBias值来修复这些精度问题,该偏差值足以覆盖已知的最大精度误差。
预防措施
-
浮点运算使用准则:
- 对安全性敏感的计算避免使用浮点运算
- 必须使用时,确保最大精度误差在安全范围内
- 考虑使用区间运算确定最大精度误差
- 对计算结果而非输入进行安全检查
-
整数运算注意事项:
- 密切关注降低精度的运算(除法、右移)
- 考虑使用更高精度的中间表示
-
漏洞发现方法:
- 源代码人工审计
- 针对接近图像边界的值进行模糊测试
- 对可疑代码区域进行暴力遍历测试
结论
图形渲染库中的精度问题可能导致严重的安全漏洞。开发者需要特别注意浮点和整数运算中的精度误差,特别是在处理图形边界时。通过合理的设计和严格的安全检查,可以有效地预防这类问题的发生。