recloudstream / recloudstream/cloudstream

Bug: `Zplayer.Upstream` extractor shadows `UpstreamExtractor` — wrong extractor wins for upstream.to URLs due to reverse-iteration dispatch

Open
#3,016 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
10.7k
Forks
1.1k
Avg merge
1d 23h
Merged PRs (30d)
15

Description

Steps to reproduce
  1. A provider returns a video URL on upstream.to (e.g. https://upstream.to/embed-abc123.html)
  2. loadExtractor() dispatch (ExtractorApi.kt:902–971) iterates extractors in reverse order (last-registered wins)
  3. Both UpstreamExtractor (library/src/commonMain/.../extractors/UpstreamExtractor.kt) and Zplayer.Upstream (library/src/commonMain/.../extractors/Zplayer.kt) match the upstream.to domain
  4. Due to reverse iteration, Zplayer.Upstream wins
Expected behavior

The canonical UpstreamExtractor should handle upstream.to URLs, OR the two should be merged/unified. Having two extractors for the same domain with different extraction logic is a footgun.

Actual behavior

Zplayer.Upstream (defined as a nested class inside Zplayer.kt) shadows UpstreamExtractor. Whichever was registered last wins — and registration order depends on file loading order, which is fragile.

If Zplayer.Upstream's extraction logic is outdated or broken, upstream.to URLs silently fail even though UpstreamExtractor would have worked.

Cloudstream version and commit hash

4.7.0 bfb85ca

Android version

Found via static code analysis. Reproducible on any Android version when an extension returns an upstream.to URL.

Logcat

N/A — silent failure or wrong extractor runs.

Other details

Location:

  • library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/UpstreamExtractor.kt
  • library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Zplayer.kt (contains a nested Upstream class with mainUrl = "https://upstream.to")

Suggested fix (pick one):

  1. Delete Zplayer.Upstream if UpstreamExtractor is the canonical one (preferred — fewer files, less confusion)
  2. Delete UpstreamExtractor if Zplayer.Upstream is newer
  3. Rename one to handle a different domain if they're actually for different sites

Severity: Medium (silent quality degradation; depends on which extractor is actually working)

Also affects: VidStack.kt has a similar issue — local object AesHelper shadows the shared helper/AesHelper.kt. Worth checking together.

Discovered during: Static code analysis of the CloudStream codebase for the CloudStream Web port (https://github.com/mindflarevortx-maker/cloudstream-web).

Acknowledgements
  • I am sure my issue is related to the app and NOT some extension.
  • I have searched the existing issues and this is a new ticket, NOT a duplicate or related to another open issue.
  • I have written a short but informative title.
  • I have updated the app to pre-release version Latest.
  • I will fill out all of the requested information in this form.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read ExtractorApi.kt:902–971 to confirm reverse-order dispatch, then compare UpstreamExtractor.kt with the nested Upstream class in Zplayer.kt. Determine which implementation is canonical and inspect the similarly named AesHelper entries in VidStack.kt and helper/AesHelper.kt if investigating the related issue. Done means upstream.to URLs have one unambiguous extractor without shadowing.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.