atlet99/dtorrent_tracker_v2

[FEATURE] - Add request parameter validation;

开放

#12 创建于 2025年11月3日

 (0 条评论) (0 个反应) (0 位负责人)Dart (0 个派生)auto 404
enhancementhelp wanted

仓库指标

星标
 (0 个星标)
PR 合并指标
 (30 天内没有已合并 PR)

描述

Description

There is no validation of input parameters before sending tracker requests. Invalid parameters (e.g., out-of-range ports, incorrect data lengths) can be sent to trackers, leading to errors or unexpected behavior.

Location

Files:

  • lib/src/tracker/http_tracker.dart (method: generateQueryParameters)
  • lib/src/tracker/udp_tracker.dart (method: generateSecondTouchMessage)
  • lib/src/tracker/tracker.dart (constructor validation)

Current Code

Parameters are used directly without validation:

// HTTP tracker - no validation
params['port'] = options['port'].toString();
params['numwant'] = options['numwant'].toString();

// UDP tracker - no validation
list.addAll(num2Uint32List(options['numwant']));
list.addAll(num2Uint16List(options['port']));

Expected Behavior

Validate all input parameters according to BEP specifications:

  1. port: Must be in range 1-65535
  2. numwant: Should be positive integer, BEP recommends maximum 50
  3. info_hash: Must be exactly 20 bytes
  4. peer_id: Must be exactly 20 bytes (if provided as binary)
  5. compact: Should be 0 or 1
  6. downloaded, uploaded, left: Should be non-negative integers

Invalid parameters should throw clear, descriptive exceptions.

Proposed Implementation

Constructor Validation

Tracker(this.id, this.announceUrl, this.infoHashBuffer, {this.provider}) {
  // Validate info_hash length
  if (infoHashBuffer.length != 20) {
    throw ArgumentError.value(
      infoHashBuffer.length,
      'infoHashBuffer',
      'Info hash must be exactly 20 bytes',
    );
  }
}

HTTP Tracker Validation

@override
Map<String, String> generateQueryParameters(Map<String, dynamic> options) {
  // Validate port
  var port = options['port'] as int?;
  if (port == null || port < 1 || port > 65535) {
    throw ArgumentError.value(
      port,
      'port',
      'Port must be in range 1-65535',
    );
  }
  
  // Validate numwant
  var numwant = options['numwant'] as int? ?? 50;
  if (numwant < 0 || numwant > 50) {
    throw ArgumentError.value(
      numwant,
      'numwant',
      'numwant must be between 0 and 50 (BEP recommendation)',
    );
  }
  
  // Validate peer_id length if provided as binary
  var peerId = options['peerId'];
  if (peerId is Uint8List && peerId.length != 20) {
    throw ArgumentError.value(
      peerId.length,
      'peerId',
      'Peer ID must be exactly 20 bytes',
    );
  }
  
  // Validate downloaded/uploaded/left are non-negative
  var downloaded = options['downloaded'] as int? ?? 0;
  var uploaded = options['uploaded'] as int? ?? 0;
  var left = options['left'] as int? ?? 0;
  
  if (downloaded < 0 || uploaded < 0 || left < 0) {
    throw ArgumentError(
      'downloaded, uploaded, and left must be non-negative integers',
    );
  }
  
  // ... rest of implementation ...
}

UDP Tracker Validation

Similar validation in generateSecondTouchMessage:

@override
Uint8List generateSecondTouchMessage(Uint8List connectionId, Map options) {
  // Validate port
  var port = options['port'] as int?;
  if (port == null || port < 1 || port > 65535) {
    throw ArgumentError.value(port, 'port', 'Port must be in range 1-65535');
  }
  
  // Validate numwant
  var numwant = options['numwant'] as int? ?? 50;
  if (numwant < 0 || numwant > 50) {
    throw ArgumentError.value(numwant, 'numwant', 'numwant must be 0-50');
  }
  
  // Validate peer_id length
  var peerId = options['peerId'];
  if (peerId is String && peerId.length != 20) {
    throw ArgumentError.value(peerId.length, 'peerId', 'Peer ID must be 20 bytes');
  }
  
  // ... rest of implementation ...
}

Impact

  • Severity: Medium (Quality Improvement)
  • Affected: All tracker requests
  • Benefits:
    • Prevents sending invalid requests to trackers
    • Clear error messages for debugging
    • Better compliance with BEP specifications
    • Catches errors early (fail-fast principle)

Additional Context

Parameter validation should happen:

  • Early (in constructors/methods that accept parameters)
  • With clear error messages
  • According to BEP specifications
  • Without breaking backward compatibility (use sensible defaults)

Related Standards

贡献者指南