fix: avoid IndexError in is_mostly_bin for short tails (#8196)

* fix: avoid IndexError in is_mostly_bin for short tails

`is_mostly_bin` looks up to 4 bytes past the 100-byte cutoff to find a
clean UTF-8 character boundary. when the input is just over 100 bytes
and starts with a continuation byte at index 100, the lookahead reads
past the end of the buffer.

cap the loop end at `len(s)`. existing fallback to `s[:100]` still
covers the case where every byte in the lookahead window is a
continuation byte.

fixes #8188

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Julio César Suástegui <juliosuas@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Julio César Suástegui 2026-04-25 03:24:59 -06:00 committed by GitHub
parent c9b063bc65
commit a8fbfc73fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 9 additions and 1 deletions

View file

@ -7,6 +7,9 @@
## Unreleased: mitmproxy next
- Fix `IndexError` in `is_mostly_bin` when exporting flows to HAR with payloads
that have a UTF-8 continuation byte at the 100-byte cutoff.
([#8196](https://github.com/mitmproxy/mitmproxy/pull/8196), @juliosuas)
## 12 April 2026: mitmproxy 12.2.2

View file

@ -132,7 +132,7 @@ def is_mostly_bin(s: bytes) -> bool:
# Cut off at ~100 chars, but do it smartly so that if the input is UTF-8, we don't
# chop a multibyte code point in half.
if len(s) > 100:
for cut in range(100, 104):
for cut in range(100, min(104, len(s))):
is_continuation_byte = (s[cut] >> 6) == 0b10
if not is_continuation_byte:
# A new character starts here, so we cut off just before that.

View file

@ -94,6 +94,11 @@ def test_is_mostly_bin():
assert not strutils.is_mostly_bin(b"aaaaa" + 50 * "𐍅".encode())
# only utf8 continuation chars
assert strutils.is_mostly_bin(150 * b"\x80")
# regression #8188: payloads with len 101-103 and a continuation byte at
# the 100-byte cutoff used to raise IndexError because the lookahead loop
# ran past the end of the string. Should not raise.
for tail in (1, 2, 3):
strutils.is_mostly_bin(b"a" * 100 + b"\x80" * tail)
def test_is_xml():