[downloader/http] Reject broken range before request
diff --git a/yt_dlp/downloader/http.py b/yt_dlp/downloader/http.py
index 10ba6102414..100d05ccdf8 100644
--- a/yt_dlp/downloader/http.py
+++ b/yt_dlp/downloader/http.py
@@ -18,6 +18,7 @@
     parse_http_range,
     sanitized_Request,
     ThrottledDownload,
+    try_get,
     write_xattr,
     XAttrMetadataError,
     XAttrUnavailableError,
@@ -53,7 +54,6 @@ class DownloadContext(dict):
 
         ctx.open_mode = 'wb'
         ctx.resume_len = 0
-        ctx.data_len = None
         ctx.block_size = self.params.get('buffersize', 1024)
         ctx.start_time = time.time()
         ctx.chunk_size = None
@@ -100,6 +100,8 @@ def establish_connection():
                 if ctx.is_resume:
                     self.report_resuming_byte(ctx.resume_len)
                 ctx.open_mode = 'ab'
+            elif req_start is not None:
+                range_start = req_start
             elif ctx.chunk_size > 0:
                 range_start = 0
             else:
@@ -116,11 +118,16 @@ def establish_connection():
             else:
                 range_end = None
 
-            if range_end and ctx.data_len is not None and range_end >= ctx.data_len:
-                range_end = ctx.data_len - 1
-            has_range = range_start is not None
-            ctx.has_range = has_range
+            if try_get(None, lambda _: range_start > range_end):
+                ctx.resume_len = 0
+                ctx.open_mode = 'wb'
+                raise RetryDownload(Exception(f'Conflicting range. (start={range_start} > end={range_end})'))
+
+            if try_get(None, lambda _: range_end >= ctx.content_len):
+                range_end = ctx.content_len - 1
+
             request = sanitized_Request(url, request_data, headers)
+            has_range = range_start is not None
             if has_range:
                 set_range(request, range_start, range_end)
             # Establish connection
@@ -151,7 +158,8 @@ def establish_connection():
                             or content_range_end == range_end
                             or content_len < range_end)
                         if accept_content_len:
-                            ctx.data_len = content_len
+                            ctx.content_len = content_len
+                            ctx.data_len = min(content_len, req_end or content_len) - (req_start or 0)
                             return
                     # Content-Range is either not present or invalid. Assuming remote webserver is
                     # trying to send the whole file, resume is not possible, so wiping the local file
@@ -159,8 +167,7 @@ def establish_connection():
                     self.report_unable_to_resume()
                     ctx.resume_len = 0
                     ctx.open_mode = 'wb'
-                ctx.data_len = int_or_none(ctx.data.info().get('Content-length', None))
-                return
+                ctx.data_len = ctx.content_len = int_or_none(ctx.data.info().get('Content-length', None))
             except (compat_urllib_error.HTTPError, ) as err:
                 if err.code == 416:
                     # Unable to resume (requested range not satisfiable)
@@ -343,7 +350,7 @@ def retry(e):
                 elif speed:
                     throttle_start = None
 
-            if not is_test and ctx.chunk_size and ctx.data_len is not None and byte_counter < ctx.data_len:
+            if not is_test and ctx.chunk_size and ctx.content_len is not None and byte_counter < ctx.content_len:
                 ctx.resume_len = byte_counter
                 # ctx.block_size = block_size
                 raise NextFragment()

## Please follow the guide below

- You will be asked some questions, please read them **carefully** and answer honestly
- Put an `x` into all the boxes [ ] relevant to your *pull request* (like that [x])
- Use *Preview* tab to see how your *pull request* will actually look like

---

### Before submitting a *pull request* make sure you have:
- [x] At least skimmed through [contributing guidelines](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions) including [yt-dlp coding conventions](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#yt-dlp-coding-conventions)
- [x] [Searched](https://github.com/yt-dlp/yt-dlp/search?q=is%3Apr&type=Issues) the bugtracker for similar pull requests
- [x] Checked the code with [flake8](https://pypi.python.org/pypi/flake8)

### In order to be accepted and merged into yt-dlp each piece of code must be in public domain or released under [Unlicense](http://unlicense.org/). Check one of the following options:
- [x] I am the original author of this code and I am willing to release it under [Unlicense](http://unlicense.org/)
- [ ] I am not the original author of this code but it is in public domain or released under [Unlicense](http://unlicense.org/) (provide reliable evidence)

### What is the purpose of your *pull request*?
- [x] Bug fix
- [ ] Improvement
- [ ] New extractor
- [ ] New feature

---

### Description of your *pull request* and other information

Funimation seems to respond with 206 even if the start is before end, while it's supposed to respond 406. It addresses that problem.

I'm not confident with the code, but at least we can download video without corrupting anything.