• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vbpf / prevail / 30757948978
86%

Build:
DEFAULT BRANCH: main
Ran 02 Aug 2026 05:10PM UTC
Jobs 2
Files 79
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

02 Aug 2026 05:01PM UTC coverage: 86.826% (+0.06%) from 86.764%
30757948978

push

github

elazarg
Type a ctx load by the bytes it reads, not by its start offset (fixes #1204)

do_load_ctx decided whether a context load touches an inline pointer field
(data/data_end/meta) from the load's start offset alone:

    const bool may_touch_ptr =
        interval.contains(desc->data) || interval.contains(desc->meta) || interval.contains(desc->end);

That is true only when the address can equal a field's first byte. A load that
starts inside or before a slot and reads across it -- `r2 = *(u32 *)(r1 + 2)`
with the harness descriptor {size=64, data=0, end=4} covers bytes [2,6) and so
reads three bytes of ctx->data plus one of ctx->data_end -- was typed T_NUM.
The register then holds real pointer bytes while the verifier believes it holds
a scalar, so the program can store it into a map shared with userspace: a
pointer/KASLR leak that the verifier reports as PASS.

The Linux kernel's ctx is_valid_access rejects such a misaligned read, so this
is major on Linux and critical for standalone deployments (userspace / Windows
eBPF), which have no kernel backstop.

Decide instead by intersecting the byte range the load actually reads,
[addr, addr + width), against each slot's range [field, field + offset_width).
This subsumes the old test -- an address equal to a field start always
intersects that field -- and additionally catches partial and straddling reads,
for a singleton address and for a range of addresses alike. A load that may
read pointer bytes leaves the destination's type havoced, exactly as an
ambiguous whole-slot load already did; a load clear of every slot is still a
plain number, narrowed by width as before.

Slots the descriptor does not define are encoded as a negative offset and are
skipped, matching the old behavior for a nonnegative address.

Also replaces three reinterpret_cast reads of the stack byte-reconstruction
buffer, and one of a scalar's bytes, with std::memcpy (part of #1206). Reading
a uint8_t[8] through uint16_t*/uint32_t*/uint64_t* is... (continued)

20 of 20 new or added lines in 2 files covered. (100.0%)

9346 of 10764 relevant lines covered (86.83%)

6274036.0 hits per line

Jobs
ID Job ID Ran Files Coverage
1 run-Debug - 30757948978.1 02 Aug 2026 05:57PM UTC 77
85.1
GitHub Action Run
2 run-Release - 30757948978.2 02 Aug 2026 05:10PM UTC 79
85.94
GitHub Action Run
Source Files on build 30757948978
  • Tree
  • List 79
  • Changed 4
  • Source Changed 3
  • Coverage Changed 4
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • Github Actions Build #30757948978
  • de799d87 on github
  • Prev Build on main (#30711478895)
  • Next Build on main (#30762301447)
  • Delete
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc