Fix synchronous recursive fetching of deeply-nested quoted posts (#35600)
This commit is contained in:
		@@ -8,9 +8,10 @@ class ActivityPub::FetchRemoteStatusService < BaseService
 | 
			
		||||
  DISCOVERIES_PER_REQUEST = 1000
 | 
			
		||||
 | 
			
		||||
  # Should be called when uri has already been checked for locality
 | 
			
		||||
  def call(uri, prefetched_body: nil, on_behalf_of: nil, expected_actor_uri: nil, request_id: nil)
 | 
			
		||||
  def call(uri, prefetched_body: nil, on_behalf_of: nil, expected_actor_uri: nil, request_id: nil, depth: nil)
 | 
			
		||||
    return if domain_not_allowed?(uri)
 | 
			
		||||
 | 
			
		||||
    @depth = depth || 0
 | 
			
		||||
    @request_id = request_id || "#{Time.now.utc.to_i}-status-#{uri}"
 | 
			
		||||
    @json = if prefetched_body.nil?
 | 
			
		||||
              fetch_status(uri, true, on_behalf_of)
 | 
			
		||||
@@ -52,7 +53,7 @@ class ActivityPub::FetchRemoteStatusService < BaseService
 | 
			
		||||
      return nil if discoveries > DISCOVERIES_PER_REQUEST
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ActivityPub::Activity.factory(activity_json, actor, request_id: @request_id).perform
 | 
			
		||||
    ActivityPub::Activity.factory(activity_json, actor, request_id: @request_id, depth: @depth).perform
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,12 @@
 | 
			
		||||
class ActivityPub::VerifyQuoteService < BaseService
 | 
			
		||||
  include JsonLdHelper
 | 
			
		||||
 | 
			
		||||
  MAX_SYNCHRONOUS_DEPTH = 2
 | 
			
		||||
 | 
			
		||||
  # Optionally fetch quoted post, and verify the quote is authorized
 | 
			
		||||
  def call(quote, fetchable_quoted_uri: nil, prefetched_quoted_object: nil, prefetched_approval: nil, request_id: nil)
 | 
			
		||||
  def call(quote, fetchable_quoted_uri: nil, prefetched_quoted_object: nil, prefetched_approval: nil, request_id: nil, depth: nil)
 | 
			
		||||
    @request_id = request_id
 | 
			
		||||
    @depth = depth || 0
 | 
			
		||||
    @quote = quote
 | 
			
		||||
    @fetching_error = nil
 | 
			
		||||
 | 
			
		||||
@@ -65,10 +68,12 @@ class ActivityPub::VerifyQuoteService < BaseService
 | 
			
		||||
    return if uri.nil? || @quote.quoted_status.present?
 | 
			
		||||
 | 
			
		||||
    status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
 | 
			
		||||
    status ||= ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: @quote.account.followers.local.first, prefetched_body:, request_id: @request_id)
 | 
			
		||||
    raise Mastodon::RecursionLimitExceededError if @depth > MAX_SYNCHRONOUS_DEPTH && status.nil?
 | 
			
		||||
 | 
			
		||||
    status ||= ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: @quote.account.followers.local.first, prefetched_body:, request_id: @request_id, depth: @depth + 1)
 | 
			
		||||
 | 
			
		||||
    @quote.update(quoted_status: status) if status.present?
 | 
			
		||||
  rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS => e
 | 
			
		||||
  rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS => e
 | 
			
		||||
    @fetching_error = e
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -83,7 +88,7 @@ class ActivityPub::VerifyQuoteService < BaseService
 | 
			
		||||
    # It's not safe to fetch if the inlined object is cross-origin or doesn't match expectations
 | 
			
		||||
    return if object['id'] != uri || non_matching_uri_hosts?(@quote.approval_uri, object['id'])
 | 
			
		||||
 | 
			
		||||
    status = ActivityPub::FetchRemoteStatusService.new.call(object['id'], prefetched_body: object, on_behalf_of: @quote.account.followers.local.first, request_id: @request_id)
 | 
			
		||||
    status = ActivityPub::FetchRemoteStatusService.new.call(object['id'], prefetched_body: object, on_behalf_of: @quote.account.followers.local.first, request_id: @request_id, depth: @depth)
 | 
			
		||||
 | 
			
		||||
    if status.present?
 | 
			
		||||
      @quote.update(quoted_status: status)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user