Skip to content

Latest commit

 

History

History
171 lines (134 loc) · 9.72 KB

File metadata and controls

171 lines (134 loc) · 9.72 KB

Mitigation Strategies Analysis for reactivex/rxjava

Mitigation Strategy: Always Dispose Subscriptions

  • Description:

    1. Identify Subscription Points: Locate all instances where subscribe() is called on an Observable or Flowable.
    2. Use CompositeDisposable (Recommended):
      • Create a CompositeDisposable instance.
      • Add each Disposable returned by subscribe() to the CompositeDisposable using compositeDisposable.add(disposable).
      • In the appropriate lifecycle method, call compositeDisposable.clear() or compositeDisposable.dispose().
    3. Use Disposable.dispose() (Alternative): Store the Disposable and call disposable.dispose() directly when needed.
    4. Use Automatic Disposal Operators: Prefer operators like takeUntil(), takeWhile(), or take(n) to automatically limit the subscription's lifetime based on another Observable or a condition.
    5. using() for Resource Management: Use using() to tie the lifetime of a resource directly to an Observable's.
  • Threats Mitigated:

    • Memory Leaks (Severity: High): Prevents Observables from holding onto subscribers indefinitely.
    • Thread Starvation (Severity: High): Releases threads held by subscriptions.
    • Unintended Side Effects (Severity: Medium): Prevents continued execution of Observable logic after it's no longer needed.
    • Resource Exhaustion (Severity: High): Releases resources held by the subscription.
  • Impact:

    • Memory Leaks: Risk reduced to near zero.
    • Thread Starvation: Risk significantly reduced.
    • Unintended Side Effects: Risk significantly reduced.
    • Resource Exhaustion: Risk significantly reduced.
  • Currently Implemented:

    • MainActivity: Uses CompositeDisposable and clear() in onDestroy().
    • NetworkService: Uses takeUntil() for lifecycle management.
    • DataRepository: Uses using() for database connections.
  • Missing Implementation:

    • BackgroundSyncService: Missing explicit disposal; needs CompositeDisposable.
    • Utility classes with static Observables: Need review.
  • Description:

    1. Understand Schedulers: Familiarize yourself with RxJava schedulers (Schedulers.io(), Schedulers.computation(), Schedulers.single(), Schedulers.newThread(), Schedulers.trampoline(), AndroidSchedulers.mainThread(), etc.).
    2. Choose Appropriately: Select the scheduler that best matches the type of work. Avoid Schedulers.newThread() unless absolutely necessary.
    3. Use subscribeOn(): Specify the scheduler for the subscription logic.
    4. Use observeOn(): Specify the scheduler for the subscriber (receiving items).
    5. Avoid Blocking Operations: Never perform blocking operations on the main thread. Use subscribeOn() and observeOn() appropriately.
    6. Custom Schedulers (Rare): If needed, ensure they use a bounded thread pool.
  • Threats Mitigated:

    • Thread Starvation (Severity: High): Prevents excessive thread creation.
    • Application Unresponsiveness (Severity: High): Prevents blocking the main thread.
    • Deadlocks (Severity: High): Proper scheduler usage helps avoid deadlocks.
  • Impact:

    • Thread Starvation: Risk significantly reduced.
    • Application Unresponsiveness: Risk eliminated with correct usage.
    • Deadlocks: Risk reduced.
  • Currently Implemented:

    • NetworkService: Uses Schedulers.io().
    • ImageProcessingUtil: Uses Schedulers.computation().
    • UI updates use observeOn(AndroidSchedulers.mainThread()).
  • Missing Implementation:

    • DatabaseService: Some operations on the main thread; needs Schedulers.io().
    • FileDownloadUtil: Uses Schedulers.newThread(); should use Schedulers.io().
  • Description:

    1. Mandatory onError: Every subscribe() call must include an onError handler.
    2. Handle the Exception: The onError handler should:
      • Log the error.
      • Attempt recovery (optional).
      • Inform the user (optional).
      • Clean up (optional).
    3. Avoid Re-throwing (Generally): Do not re-throw unless handled further up.
    4. Consider Error Handling Operators: Use operators like onErrorReturnItem(), onErrorResumeNext(), retry(), retryWhen(), or onErrorComplete() within the Observable chain.
  • Threats Mitigated:

    • Application Crashes (Severity: High): Prevents unhandled exceptions.
    • Undefined Behavior (Severity: High): Ensures graceful error handling.
    • Data Loss (Severity: Medium): Allows for retries or fallbacks.
    • Security Vulnerabilities (Severity: Low/Medium): Indirectly reduces risk.
  • Impact:

    • Application Crashes: Risk reduced to near zero.
    • Undefined Behavior: Risk significantly reduced.
    • Data Loss: Risk reduced.
    • Security Vulnerabilities: Indirectly reduces risk.
  • Currently Implemented:

    • NetworkService: onError handlers log errors and show messages.
    • DataRepository: onError handlers attempt retries and log failures.
  • Missing Implementation:

    • Utility classes: Missing onError handlers in some subscribe() calls.
    • BackgroundSyncService: Inconsistent error handling.
  • Description:

    1. Identify Debugging Points: Determine where to inspect the Observable stream.
    2. Insert doOn... Operators: Add operators like doOnNext(), doOnError(), doOnComplete(), doOnSubscribe(), doOnDispose(), doOnTerminate().
    3. Log or Inspect: Log information or use a debugger.
    4. Remove After Debugging (Optional): Remove or comment out after debugging.
  • Threats Mitigated:

    • Complex, Difficult-to-Debug Code (Severity: Medium): Allows inspection without affecting behavior.
  • Impact:

    • Complex, Difficult-to-Debug Code: Greatly simplifies debugging.
  • Currently Implemented:

    • Used sporadically.
  • Missing Implementation:

    • No consistent strategy.
  • Description:

    1. Identify Side Effects: Examine operators like map(), flatMap(), and filter() for operations modifying external state.
    2. Refactor for Purity:
      • map() and flatMap() for Transformations: Use these for data transformation only.
      • doOn... for Explicit Side Effects: If unavoidable, use doOnNext(), doOnError(), or doOnComplete() to make them explicit.
      • subscribe() for Final Actions: Use subscribe() for final actions like UI updates.
    3. Isolate Side Effects: Encapsulate complex side effects in separate methods/classes.
    4. Consider Immutable Data: Use immutable data structures.
  • Threats Mitigated:

    • Unexpected Behavior (Severity: Medium): Reduces unintended consequences.
    • Difficult Debugging (Severity: Medium): Improves code clarity.
    • Concurrency Issues (Severity: Medium): Reduces race conditions.
  • Impact:

    • Unexpected Behavior: Significantly reduces risk.
    • Difficult Debugging: Improves clarity.
    • Concurrency Issues: Reduces risk.
  • Currently Implemented:

    • Some effort in DataRepository.
  • Missing Implementation:

    • BackgroundSyncService and UI components: Side effects within map() and flatMap().
  • Description:

    1. Favor Observables/Flowables: Prioritize Observable.create(), Observable.fromCallable(), etc.
    2. Encapsulate Subjects: Keep Subjects private; expose only the Observable interface.
    3. Select Appropriate Subject Type: Choose PublishSubject, BehaviorSubject, ReplaySubject, or AsyncSubject based on needs.
    4. Centralize Emission Logic: Avoid calling onNext(), onError(), onComplete() from multiple locations.
    5. Explore Alternatives: Consider share(), publish().refCount(), or event bus libraries.
  • Threats Mitigated:

    • Tight Coupling (Severity: Medium): Reduces dependencies.
    • Difficult Debugging (Severity: Medium): Improves data flow understanding.
    • Unexpected Behavior (Severity: Medium): Reduces unintended consequences.
    • Concurrency Issues (Severity: Medium): Reduces race conditions.
  • Impact:

    • Tight Coupling: Significantly reduces coupling.
    • Difficult Debugging: Improves clarity.
    • Unexpected Behavior: Reduces risk.
    • Concurrency Issues: Reduces risk.
  • Currently Implemented:

    • DataRepository uses Subjects internally, exposes Observables.
  • Missing Implementation:

    • BackgroundSyncService: Extensive, public Subject use.
    • UI components: Subjects used as a simple event bus.