Debian Patches

Status for libskia/146.20260414~git.ef5f213+dfsg-3

Patch Description Author Forwarded Bugs Origin Last update
build-files Debian-specific makefile. Filip Strömbäck <filip@fprg.se> not-needed
unsupported-attributes Remove unsupported annotations. Filip Strömbäck <filip@fprg.se> not-needed
vk_malloc-location Use system library of vk_mem_alloc.h. Filip Strömbäck <filip@fprg.se> not-needed
loong-build Patches to make loong64 build work with GCC. Filip Strömbäck <filip@fprg.se> yes
CVE-2026-5870 Upstream patch for CVE-2026-5870, from m147 (commit 4502f88af90279ad2685528bd3cf7e90ab140f19) Stephen Nusko <nuskos@google.com> not-needed upstream https://skia-review.googlesource.com/c/skia/+/1194336
CVE-2026-7920 Make local optimized copy of program when creating SkRP version
As per the linked bug, there could be a problem if the gpu backend
tried to use a compiled runtime effect at the same time as the
cpu backend made its first call to getRPProgram(). This could result
in the fBaselineProgram being mutated out from under the gpu backend's
version.

This makes an optimized copy of the existing program to then convert
to SkRasterPipeline. By setting optimize to true and a non-zero
inlining limit, compiler.convertProgram will call the inliner and
remove unused functions (as well as other things like unused
local/global variables).

To prevent further mutation of fBaseProgram, I made it be pointer
to const (I'd initially been puzzled how a const getRPProgram could
be mutating it, but only the pointer was const).

Performance change looks negligible (parsing is pretty quick):
```
$ out/Release/nanobench_baseline --match sksl_skrp
Timer overhead: 23.5ns
curr/maxrss loops min median mean max stddev samples config bench
92/90 MB 3 5.35µs 5.38µs 5.38µs 5.45µs 0% █▅▁▃▃▄▄▂▃▃ nonrendering sksl_skrp_tiny
92/90 MB 3 14.7µs 14.9µs 15.1µs 17.5µs 6% █▂▁▁▁▁▁▁▁▁ nonrendering sksl_skrp_small
92/90 MB 1 125µs 132µs 135µs 164µs 9% █▅▃▂▂▁▂▁▁▄ nonrendering sksl_skrp_medium
92/90 MB 1 321µs 338µs 339µs 364µs 5% █▆▃▂█▄▂▁▅▂ nonrendering sksl_skrp_large

$ out/Release/nanobench_with_change --match sksl_skrp
Timer overhead: 23.5ns
curr/maxrss loops min median mean max stddev samples config bench
92/90 MB 3 5.62µs 5.64µs 5.64µs 5.69µs 0% █▂▄▄▃▃▄▁▅▃ nonrendering sksl_skrp_tiny
92/90 MB 4 14.8µs 14.9µs 15.3µs 17.1µs 5% █▂▁▁▅▁▁▁▁▁ nonrendering sksl_skrp_small
92/90 MB 2 125µs 130µs 131µs 154µs 7% █▃▂▂▂▁▁▂▁▃ nonrendering sksl_skrp_medium
92/90 MB 1 322µs 344µs 342µs 369µs 5% █▆▅▃▂▁▇▄▂▃ nonrendering sksl_skrp_large
```
Kaylee Lubick <kjlubick@google.com> yes upstream 2026-04-27
CVE-2026-7923 Avoid removing too many stack entries in SkRP during discard_stack
Consider an sksl snippet like:
```
half4 main(float2 xy) {
float4 v = float4(xy.x, -1.0, -2.0, -3.0);
v = abs(v);
return half4(v);
}
```

this could be turned into (unoptimized) instructions like [1]
```
store_src_rg xy = src.rg
init_lane_masks CondMask = LoopMask = RetMask = true
copy_slot_unmasked v(0) = xy(0)
copy_constant v(1) = 0xBF800000 (-1.0)
copy_constant v(2) = 0xC0000000 (-2.0)
copy_constant v(3) = 0xC0400000 (-3.0)
copy_4_slots_unmasked $0..3 = v # unnecessary
bitwise_and_imm_4_ints $0..3 &= 0x7FFFFFFF
copy_4_slots_unmasked v = $0..3
load_src src.rgba = $0..3
```
( the bitwise_and_imm_4_ints instruction is the abs() part, masking
off the sign bit)

We can optimize cases where we push to the stack (e.g.
the copy_4_slots_unmasked), do an operation (the &=) and then
pop the value off the stack into just doing the operation w/o
involving the stack. (We might have to push the result to the
stack for further use).
```
...
copy_constant v(3) = 0xC0400000 (-3.0)
bitwise_and_imm_4_ints v &= 0x7FFFFFFF
copy_4_slots_unmasked $0..3 = v
load_src src.rgba = $0..3
```

There was a bug in the optimization where we removed *all* the
slots for an instruction (4 in this case because it's a float4)
even though the call was discard_stack(1). This would be followed
up by a call to discard_stack(3) (the remainder of the previous
instruction's stack) and we'd underflow the stack.

Problematic sksl:
```
half4 main(float2 xy) {
float4 v;
v.x += xy.x;
(v = abs(v)).xyz; # drop 1 channel (the .w)
return half4(v);
}
// This was in the output
bitwise_and_imm_4_ints v &= 0x7FFFFFFF
copy_4_slots_unmasked ExternalPtr(0..3) = v
load_src src.rgba = ExternalPtr(0..3)
```

where ExternalPtr is referring to memory outside any variables,
uniforms, or the temporary stack. Yikes! I'll keep that in mind
for the future.

Anyway, for the fix, we'll only remove N slots if the previous
call was N slots wide.

[1] e.g. bazel build //tools/skslc && bazel-bin/tools/skslc/skslc input.sksl output.skrp
Kaylee Lubick <kjlubick@google.com> yes upstream 2026-04-27
CVE-2026-7949 Use a local data copy for strike deserialization
The readStrikeData() input is volatile (shared memory) and untrusted.

To avoid time-of-check to time-of-use issues during deserialization,
always make a copy when transitioning to internal/non-volatile APIs.

This is similar to the other defensive copies used in Chromium's
cc/paint_op deserialization, e.g. [1].

[1] https://source.chromium.org/chromium/chromium/src/+/main:cc/paint/paint_op_reader.cc;drc=9c91b2494d4bf0a2d33b5985f7d1af79e72146f2;l=329
Florin Malita <fmalita@google.com> yes upstream 2026-03-27

All known versions for source package 'libskia'

Links