You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
formarkinmarks:
ifsequence.startswith(mark):
returniana_encoding, mark
You can see that this list is processed in a loop, with the function exiting on the first startswith match. This means that if the first element of the list, b"\x2b\x2f\x76\x38", matches, the loop doesn't reach the last one, b"\x2b\x2f\x76\x38\x2d". If the first doesn't match, the last one doesn't match either, since it starts with the same four bytes. Therefore, the fifth substring does nothing but add an additional delay during execution.
Also, I don't understand where the fifth substring of five bytes came from. Wikipedia only mentions four-byte substrings:
UTF-7: 2B 2F 76
...
Followed by 38, 39, 2B, or 2F (ASCII 8, 9, + or /), depending on what the next character is.
According to a 2012-11-25 contribution to Wikipedia's Byte Order Mark article, a contribution that remained in place until 2020-09-24, and so I think should be reliable, there is a special-case for an empty-string, in which the 38 hex suffix char is followed by a 2D hex char. This applies in the case of an empty string -- and that line represents it.
However: yes, given that the startswith conditional seems to be the only usage of this bytemark within the list, and that it'll never match given the self-prefix that precedes it, I think it should be fine to remove. Ref:
I think there's more to this than it may first appear.
In particular, UTF7 encoding of content that contains a standalone Byte-Order-Mark character is not yet handled correctly by charset_normalizer, as far as I can tell.
I still don't understand the logic of checking for a 5-byte string if it starts with the same 4-byte string. It just adds an extra check, nothing more.
The additional pattern can't make a difference to the encoding detection functionality -- but it could affect another feature: charset_normalizer can subtract the matched prefix-with-BOM bytepattern from the stream, allowing the data consumer to retrieve the content.
...except that the pattern we're discussing is at the end of the utf_7 list -- so it has never been subtracted from content streams, so far (and indeed has been entirely unused, as you mentioned to begin with). But it does have a possible use.
I'm now doubting whether an UTF7 stream that begins with the 2b 2f 76 38 2d pattern guarantees that the content is empty -- I think it's more likely that an empty content is one of many possible valid content-streams with that prefix. And if so, subtracting it from the start of the stream is likely incorrect, because we'll have trimmed a leading byte (2d) from the bytestream.
I think the BOM should be trimmed after decoding, not before, because in Python it always turns into FEFF, whatever it is in the byte string.
I'd agree with that; I explored a few simple examples, and I think that the existing trimming logic in combination with the current BOM patterns can cause subsequent content to be decoded incorrectly -- I've filed #718 to describe that (apologies if it seems to duplicate/distract from this issue -- I think it is a slightly separate problem, though).
Activity
jayaddison commentedon Mar 16, 2026
According to a 2012-11-25 contribution to Wikipedia's
Byte Order Markarticle, a contribution that remained in place until 2020-09-24, and so I think should be reliable, there is a special-case for an empty-string, in which the38hex suffix char is followed by a2Dhex char. This applies in the case of an empty string -- and that line represents it.However: yes, given that the
startswithconditional seems to be the only usage of this bytemark within the list, and that it'll never match given the self-prefix that precedes it, I think it should be fine to remove. Ref:charset_normalizer/src/charset_normalizer/utils.py
Lines 291 to 299 in 5478b84
jayaddison commentedon Mar 16, 2026
I think there's more to this than it may first appear.
In particular, UTF7 encoding of content that contains a standalone Byte-Order-Mark character is not yet handled correctly by
charset_normalizer, as far as I can tell.(we should expect the result of that script to be an empty string, I think)
PalmtopTiger commentedon Mar 17, 2026
I still don't understand the logic of checking for a 5-byte string if it starts with the same 4-byte string. It just adds an extra check, nothing more.
"\U0001F415" - the dog emoji.
jayaddison commentedon Mar 17, 2026
The additional pattern can't make a difference to the encoding detection functionality -- but it could affect another feature:
charset_normalizercan subtract the matched prefix-with-BOM bytepattern from the stream, allowing the data consumer to retrieve the content....except that the pattern we're discussing is at the end of the
utf_7list -- so it has never been subtracted from content streams, so far (and indeed has been entirely unused, as you mentioned to begin with). But it does have a possible use.jayaddison commentedon Mar 17, 2026
I'm now doubting whether an UTF7 stream that begins with the
2b 2f 76 38 2dpattern guarantees that the content is empty -- I think it's more likely that an empty content is one of many possible valid content-streams with that prefix. And if so, subtracting it from the start of the stream is likely incorrect, because we'll have trimmed a leading byte (2d) from the bytestream.PalmtopTiger commentedon Mar 17, 2026
I think the BOM should be trimmed after decoding, not before, because in Python it always turns into FEFF, whatever it is in the byte string.
jayaddison commentedon Mar 19, 2026
I'd agree with that; I explored a few simple examples, and I think that the existing trimming logic in combination with the current BOM patterns can cause subsequent content to be decoded incorrectly -- I've filed #718 to describe that (apologies if it seems to duplicate/distract from this issue -- I think it is a slightly separate problem, though).
fix: correctly remove SIG remnant in utf-7 decoded string
⚡ Remove redundant UTF7 BOM (#730)
jayaddison commentedon Apr 3, 2026
@PalmtopTiger this should be fixed now; the redundant substring has been removed by PR #730
PalmtopTiger commentedon Apr 3, 2026
@jayaddison thank you
jawah/charset_normalizer at 5478b84058a2 with the tests from PR #717