Skip to content

disallow the "surrogatepass" handler for non utf-* encodings #58124

Closed

Description

@kennyluck
mannequin
BPO 13916
Nosy @loewis, @vstinner, @ezio-melotti, @serhiy-storchaka
Files
  • surrogatepass_non_utf.patch
  • surrogatepass_cp_utf8.patch
  • surrogatepass_cp65001.patch
  • cp_encoding_name.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/vstinner'
    closed_at = None
    created_at = <Date 2012-01-31.23:51:10.468>
    labels = ['type-feature', 'expert-unicode']
    title = 'disallow the "surrogatepass" handler for non utf-* encodings'
    updated_at = <Date 2014-08-17.15:19:53.801>
    user = 'https://bugs.python.org/kennyluck'

    bugs.python.org fields:

    activity = <Date 2014-08-17.15:19:53.801>
    actor = 'serhiy.storchaka'
    assignee = 'vstinner'
    closed = False
    closed_date = None
    closer = None
    components = ['Unicode']
    creation = <Date 2012-01-31.23:51:10.468>
    creator = 'kennyluck'
    dependencies = []
    files = ['35257', '35259', '35262', '35264']
    hgrepos = []
    issue_num = 13916
    keywords = ['patch']
    message_count = 20.0
    messages = ['152416', '159520', '159525', '159528', '218597', '218600', '218601', '218602', '218603', '218605', '218611', '218612', '218613', '218615', '218617', '218655', '218658', '218659', '218740', '225448']
    nosy_count = 6.0
    nosy_names = ['loewis', 'vstinner', 'ezio.melotti', 'python-dev', 'kennyluck', 'serhiy.storchaka']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue13916'
    versions = ['Python 3.5']

    Linked PRs

    Activity

    1. kennyluck commented on Jan 31, 2012

      kennyluckmannequin
      MannequinAuthor

      Currently the "surrogatepass" handler always encodes the surrogates in UTF-8 and hence the behavior for, say, "\udc80".encode("latin-1", "surrogatepass").decode("latin-1") might be unexpected and I don't even know what would, say, "\udc80\udc80".encode("big5", "surrogatepass").decode("big5"), return. Regardless of the fact that the documentation says "surrogatepass" is specific to utf-8", the currently behavior is arguably not too harmful thanks to PyBytesObject's '\0' ending (so that ((p[0] & 0xf0) == 0xe0 || (p[1] & 0xc0) == 0x80 || (p[2] & 0xc0) == 0x80) in PyCodec_SurrogatePassErrors would not crash).

      However, I suggest we have the system either 1) raise early LookupError 2) raise the original Unicode(Decode|Encoding)Exception as soon as PyCodec_SurrogatePassErrors is called. I prefer the former.

      Having this could shorten PyCodec_SurrogatePassErrors significantly in the patch I will shortly submit for issue bpo-12892 as all the error conditions for utf-8, utf-16 and utf-32 are predicable* and almost all the conditionals could be removed. (The * statement is arguable if someone initializes interp->codec_search_path before _PyCodecRegistry_Init and the utf-16/32 encoders are overwritten. I don't think we need to worry about this too much though. Or am I wrong here?)

    2. loewis commented on Apr 28, 2012

      loewismannequin
      Mannequin

      I fail to see the problem. If the error handler does not produce meaningful results in some context, then just don't use it.

      The whole point of error handlers is that they handle errors; using them shouldn't ever cause errors/exceptions.

    3. serhiy-storchaka commented on Apr 28, 2012

      @serhiy-storchaka
      Member

      The problem is that "surrogatepass" specific to utf-8 and there is no standard way to decode alone surrogates in utf-16.

      >>> "\udc80\udc80".encode("utf-16", "surrogatepass").decode("utf-16", "surrogatepass")
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      UnicodeDecodeError: 'utf16' codec can't decode bytes in position 2-3: illegal encoding

      With utf-32 this "works" only thanks to the bug -- utf-32 allows alone surrogates (issue bpo-12892).

      If the "surrogatepass" worked with utf-16 and utf-32, it would be natural to throw ValueError for other encodings.

    4. loewis commented on Apr 28, 2012

      loewismannequin
      Mannequin

      I see. The proper reaction for a codec that can't handle a certain error then is to raise the original exception. I'm -1 on raising LookupError when trying to find the error handler - this would suggest that the error handler does not exist, which is not true.

      As for simplifying the implementation: it might be reasonable to special-case surrogatepass inside the individual codecs, rather than looking up the error handler. Then the error handler could just be identical to "strict", except that UTF-8, UTF-16, and UTF-32 individually special-case this error handler in their encoders and decoders.

    5. serhiy-storchaka commented on May 15, 2014

      @serhiy-storchaka
      Member

      This issue was mainly resolved in bpo-12892. The surrogatepass error handler now works with UTF-16* and UTF-32* encodings. But for other encodings it behaves as for UTF-8 (preserve old behavior). Should we change the behavior for non-UTF encodings end raise an exception (as for "strict")?

    6. serhiy-storchaka commented on May 15, 2014

      @serhiy-storchaka
      Member

      Here is a patch which disallows the surrogatepass handler for non-utf encodings. Please test it on Windows.

    7. added
      type-featureA feature request or enhancement
      and removed
      type-bugAn unexpected behavior, bug, or error
      on May 15, 2014
    8. vstinner commented on May 15, 2014

      @vstinner
      Member

      Serhiy Storchaka wrote:

      Here is a patch

      I don't see your patch.

    9. serhiy-storchaka commented on May 15, 2014

      @serhiy-storchaka
      Member

      Oh, sorry.

    10. loewis commented on May 15, 2014

      loewismannequin
      Mannequin

      LGTM

    11. python-dev commented on May 15, 2014

      python-devmannequin
      Mannequin

      New changeset 5e98a50e0f55 by Serhiy Storchaka in branch 'default':
      Issue bpo-13916: Disallowed the surrogatepass error handler for non UTF-*
      http://hg.python.org/cpython/rev/5e98a50e0f55

    12. 16 remaining items

    13. StanFromIreland commented on Jul 12, 2025

      @StanFromIreland
      Member

      Is this still a valid issue? I do not see any Windows buildbot failing this test?

    14. added a commit that references this issue on Aug 5, 2025
    15. vstinner commented on Aug 5, 2025

      @vstinner
      Member

      But an exception reports about CP_UTF8.

      I wrote #137415 to change that. It's based on my old cp_encoding_name.patch attached to this issue.

    16. added a commit that references this issue on Aug 6, 2025
    17. added 2 commits that reference this issue on Aug 6, 2025
    18. added a commit that references this issue on Aug 6, 2025
    19. vstinner commented on Aug 7, 2025

      @vstinner
      Member

      I close the issue. The last point (CP_UTF8) has been addressed.

    20. added a commit that references this issue on Aug 19, 2025
    21. added a commit that references this issue on Oct 7, 2025
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    OS-windowsstdlibStandard Library Python modules in the Lib/ directorytopic-unicodetype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions