Commit Graph
77 Commits
Author SHA1 Message Date
Karl Seguin c40e6c5b94 cdp: follow redirects on request interception fulfillment
Fixes https://github.com/lightpanda-io/browser/issues/2828
2026-06-29 10:48:37 +08:00
Karl Seguin 0aaa77c7e6 minor: remove unused imports 2026-06-27 18:16:31 +08:00
Karl Seguin f2eaeb1c9a uaf: Prevent double-free on BrowserContext deinit with pending interception
Adds a abortParked (to be used instead of abort for a parked transfer) which
guards against a double-free by setting the state to .completing BEFORE running
the requestFailed callback. Without this, requestFail could itself cause the
transfer to be cleared.

Also added a guard to try to catch double transfer deinit's in Debug. Because
the memory could get re-used between the first and second free, the lack of
failure doesn't prove there is no UAF. But it's cheap to do and debug only.
2026-06-24 20:09:00 +08:00
Pierre Tachoire 5d62fdc0fc Merge pull request #2773 from lightpanda-io/internal-request-flag
Internal Flag on Request
2026-06-19 15:18:02 +00:00
Muki Kiboigo d891084a8b add internal flag to Request 2026-06-17 20:41:11 -07:00
Muki Kiboigo 438a5f4320 properly use response headers for renew 2026-06-17 20:30:14 -07:00
Muki Kiboigo 47483fd992 update more fields on renew 2026-06-16 22:13:08 -07:00
Muki Kiboigo 9aed4a20e7 remove dead code from Forward 2026-06-16 21:35:00 -07:00
Muki Kiboigo 515ae12ab4 free cached response data on eviction 2026-06-15 07:31:30 -07:00
Muki Kiboigo f4db7c7e94 send both etag and last modified if present on revalidation 2026-06-15 07:20:21 -07:00
Muki Kiboigo be3aadf739 clean stale entry on error or shutdown if present 2026-06-15 07:20:21 -07:00
Muki Kiboigo 2414a67d28 header callback returns a HeaderResult 2026-06-14 09:17:26 -07:00
Muki Kiboigo 38c2fcdf7b working cache revalid 2026-06-14 09:17:26 -07:00
Muki Kiboigo 2fd9e5231b better handling of stale entry 2026-06-14 09:17:26 -07:00
Muki Kiboigo fff8ec8a8a send served from cache notification in one place 2026-06-14 09:17:26 -07:00
Muki Kiboigo b99521c738 simplify CacheLayer request logic 2026-06-14 09:17:26 -07:00
Muki Kiboigo 2728cfc65e Cache.revalidate -> Cache.renew 2026-06-14 09:17:25 -07:00
Muki Kiboigo 17f3bf557b properly notify and serve from cache on revalidation 2026-06-14 09:17:25 -07:00
Muki Kiboigo feefcd4650 Cache Revalidation 2026-06-14 09:16:33 -07:00
Muki Kiboigo a6c8a28977 add Cache.revalidate + supporting logic 2026-06-14 09:16:31 -07:00
Muki Kiboigo 572267802d fire RobotsBlocked in nextTickRun 2026-06-05 07:25:32 -07:00
Muki Kiboigo ffcdcc6e09 add optional ctx to runNextTick 2026-06-05 07:25:29 -07:00
Adrià Arrufat ee21138bde fix: drop orphaned deferred contexts on frame teardown
A fetch() deferred behind a parser-blocking script keeps a DeferredContext
in the DeferringLayer whose forward.ctx points at the Fetch struct, which
lives in a page/session arena. If the transfer completes while deferred,
it is deinited and unlinked from the frame owner, so abortTransfers ->
abortOwner can't reach the now-orphaned context. It lingers in the active
list, and when the page is torn down its Fetch arena is freed; a later
flushFrame (e.g. the next page's parser-blocking script popping) replays
the buffered header callback into the freed Fetch -> use-after-free.

Add DeferringLayer.cancelFrame to drop these orphaned (terminal) contexts
during Frame.abortTransfers. Non-terminal contexts still have a live
transfer that cleans them up through its own callback path, so they are
left alone.
2026-06-05 09:47:15 +02:00
Karl Seguin 720e610542 Merge pull request #2625 from lightpanda-io/deferring_layer_error_handling
DeferringLayer correctly handle header stop/errors
2026-06-03 20:57:36 +08:00
Karl Seguin 205865f96c DeferringLayer correctly handle header stop/errors
When forwardHeader signals not to proceed, fire() should stop.

This is the direct fix to https://github.com/lightpanda-io/browser/issues/2622
2026-06-03 18:13:32 +08:00
Karl Seguin 20555150dd Fix two issues with DeferringLayer
The first is that it can outlive the Transfer and thus has to dupe anything
it'll use (e.g. the frame_id off the request).

The second is that flushFrame is reentrant (flushFrame -> fire -> flushFrame)
and that results in the active list and list pointers becoming invalid.
2026-06-03 17:31:40 +08:00
Karl Seguin f7a32c05a8 Improve / fix InterceptLayer.intercepted count tracking
The intercept state is currently split and hard to keep consistent and even
just reason about. InterceptLayer keeps the `intercepted` count, but CDP's
`BrowserContext` has its intercepted lookup. This isn't a problem per se, but
you BrowserContext.deinit tries to decrement `InterceptLayer.intercepted` which
is only safe if we can guarantee that the two are in sync. Which we can't.

This commit simplifies the upkeep of `InterceptLayer.intercepted` and uses the
Transfer's state on unpark/deinit to decrement it. The CDP layer no longer
cares about / has to maintain the count.

Driven by this crash report:

BrowserContext.deinit.intercepted
---
value: 0
/home/runner/work/browser/browser/src/lightpanda.zig:279:25: 0x2871842 in deinit (lightpanda)
/home/runner/work/browser/browser/src/cdp/CDP.zig:127:18: 0x28c3f45 in deinit (lightpanda)
/home/runner/work/browser/browser/src/Server.zig:186:21: 0x2827997 in handleConnection (lightpanda)
/home/runner/work/_temp/6dc322a8-c74f-4990-9660-4cc6dcfb9352/zig-x86_64-linux-0.15.2/lib/std/Thread.zig:509:13: 0x269c233 in entryFn (lightpanda)
???:?:?: 0x7fce7ccabd57 in ??? (libc.so.6)
Unwind information for `libc.so.6:0x7fce7ccabd57` was not available, trace may be incomplete

on 1.0.0-nightly.6542+94ba0791
2026-06-03 08:24:47 +08:00
Karl Seguin 1895d8f58d Merge pull request #2329 from lightpanda-io/deferred-layer
Deferred Layer
2026-06-02 12:43:06 +08:00
Karl Seguin e333e458b1 Merge pull request #2597 from lightpanda-io/remove_unused_imports
remove unused imports
2026-06-02 06:24:30 +08:00
Karl Seguin 37a846d91d remove unused imports 2026-06-01 22:42:39 +08:00
Muki Kiboigo 2f1362ac19 remove missing queue panic on RobotsLayer 2026-06-01 06:57:14 -07:00
Muki Kiboigo 5b4b978347 minor cleanup of DeferringLayer 2026-06-01 06:23:43 -07:00
Muki Kiboigo 51d8c8e8d8 prevent double frees on shutdown with DeferredContext 2026-06-01 06:23:43 -07:00
Muki Kiboigo 444884fb81 remove unneeded flushUnblocked 2026-06-01 06:23:42 -07:00
Muki Kiboigo 342ce9b1d9 firePartial should always have a stable response 2026-06-01 06:23:42 -07:00
Muki Kiboigo 673403f950 properly flush frame after syncRequest eval 2026-06-01 06:23:42 -07:00
Muki Kiboigo 9ab82d2761 add DeferringLayer 2026-06-01 06:23:40 -07:00
Muki Kiboigo a4c535370b add optional Abort handler to runNextTick 2026-05-25 11:05:11 -07:00
Muki Kiboigo 00ccb5ed52 NextTickNode is owned by Transfer 2026-05-25 10:52:51 -07:00
Muki Kiboigo f4de603cf5 properly deinit transfer on runNextTick 2026-05-25 10:09:53 -07:00
Muki Kiboigo 766e163ef1 properly handle cancellation of next tick events 2026-05-25 10:06:50 -07:00
Muki Kiboigo a295a7a21a various changes to properly track next ticked transfers 2026-05-25 10:06:50 -07:00
Muki Kiboigo cd5e5ece40 serve from cache on next client tick 2026-05-25 10:06:49 -07:00
Karl Seguin 1cdd2bb324 Cleanup Transfer flag
Replaces 4 boolean flags with a state. Makes it easier to figure out what the
state of the transfer is, and removes the possibility of inconsistent flags
.e.g queued + loop_owned.

loop_owned -> state != .created
_queued -> state == .queued
_perform -> state == .completing
aborted -> state == .aborted
2026-05-20 20:37:21 +08:00
Karl Seguin a5162bea8f Cleanup HttpClient.Transfer
This is just moving fields around. The end result is that there's a
`transfer.req` and a `transfer.res`.

On the Request side, we use to have a nested `params: RequestParam` resulting
in a lot of `transfer.req.params.url`. This is now `transfer.req.url`. On the
Response side, we had the exact opposite: response fields splattered directly
in the transfer, `transfer.response_header`. This is now `transfer.res.header`.

There is now an HttpClient.Response, which is the actual final response (which
could be for a transfer or something else, e.g the cache). And an
HttpClient.Transfer.Response which captures the inflight response data (and is
one of the polymorphic variants of the HttpClient.Response). Probably still not
ideal, but I'm not sure how to make it cleaner, and even if this is just an
intermediary step, I consider it an small win.
2026-05-15 12:55:47 +08:00
Muki Kiboigo 940976b6a7 properly disable cache on Network.setCacheDisabled 2026-05-14 09:03:51 -07:00
Muki Kiboigo ac863c7e2b add Network.requestServedFromCache 2026-05-13 21:47:47 -07:00
Muki Kiboigo 4a45b4d866 fix crash on robots.txt request fufilled immediately 2026-05-12 21:50:05 -07:00
Karl Seguin 50b126b402 fix cachelayer hit path 2026-05-13 07:14:44 +08:00
Karl Seguin 5e0976bbd6 fix use-after-free on robotslayer shutdown 2026-05-12 19:26:24 +08:00