Skip to content

range_error function always return true! #1946

Closed
@bobhyun

Description

@bobhyun

If there's Range in the Request header, it always failed with 416 status.

In my case, using Visual Studio 2022 C++, the value -1 is the same as SIZE_MAX
in range_error function,
ssize_t prev_first_pos = -1;
ssize_t prev_last_pos = -1;
The comparision with these values always be the same or less.

inline bool range_error(Request &req, Response &res) {
  if (!req.ranges.empty() && 200 <= res.status && res.status < 300) {
    ssize_t contant_len = static_cast<ssize_t>(
        res.content_length_ ? res.content_length_ : res.body.size());

    ssize_t prev_first_pos = -1; // The value -1 is the same as SIZE_MAX
    ssize_t prev_last_pos = -1;
    size_t overwrapping_count = 0;

    // NOTE: The following Range check is based on '14.2. Range' in RFC 9110
    // 'HTTP Semantics' to avoid potential denial-of-service attacks.
    // https://www.rfc-editor.org/rfc/rfc9110#section-14.2

    // Too many ranges
    if (req.ranges.size() > CPPHTTPLIB_RANGE_MAX_COUNT) { return true; }

    for (auto &r : req.ranges) {
      auto &first_pos = r.first;
      auto &last_pos = r.second;

      if (first_pos == -1 && last_pos == -1) {
        first_pos = 0;
        last_pos = contant_len;
      }

      if (first_pos == -1) {
        first_pos = contant_len - last_pos;
        last_pos = contant_len - 1;
      }

      if (last_pos == -1) { last_pos = contant_len - 1; }

      // Range must be within content length
      if (!(0 <= first_pos && first_pos <= last_pos &&
            last_pos <= contant_len - 1)) {
        return true;
      }

      // Ranges must be in ascending order
      if (first_pos <= prev_first_pos) { return true; } // so this condition always true

      // Request must not have more than two overlapping ranges
      if (first_pos <= prev_last_pos) {  // it's the same as here
        overwrapping_count++;
        if (overwrapping_count > 2) { return true; }
      }

      prev_first_pos = (std::max)(prev_first_pos, first_pos);
      prev_last_pos = (std::max)(prev_last_pos, last_pos);
    }
  }

  return false;
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions