GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Different behavior of C and Python impls of datetime.strftime with non-UTF-8-encodable strings · Issue #78662 · python/cpython

Different behavior of C and Python impls of datetime.strftime with non-UTF-8-encodable strings #78662

New issue
Copy link
New issue
Copy link
Closed
Closed
Different behavior of C and Python impls of datetime.strftime with non-UTF-8-encodable strings#78662
Copy link
Assignees
serhiy-storchaka
Labels
3.12only security fixesonly security fixes3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

izbyshev
mannequin
opened on Aug 23, 2018
Issue body actions
BPO 34481
Nosy @brettcannon, @abalkin, @pitrou, @vstinner, @taleinat, @serhiy-storchaka, @pganssle, @izbyshev
PRs
  • bpo-34481: Fix surrogate-handling in strftime #8983
  • 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 = None
    closed_at = None
    created_at = <Date 2018-08-23.17:40:57.476>
    labels = ['extension-modules', '3.8', 'type-bug', '3.7']
    title = 'Different behavior of C and Python impls of datetime.strftime with non-UTF-8-encodable strings'
    updated_at = <Date 2018-09-05.15:38:31.222>
    user = 'https://github.com/izbyshev'

    bugs.python.org fields:

    activity = <Date 2018-09-05.15:38:31.222>
    actor = 'rhettinger'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Extension Modules']
    creation = <Date 2018-08-23.17:40:57.476>
    creator = 'izbyshev'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 34481
    keywords = ['patch']
    message_count = 8.0
    messages = ['323963', '324329', '324336', '324337', '324356', '324397', '324401', '324630']
    nosy_count = 8.0
    nosy_names = ['brett.cannon', 'belopolsky', 'pitrou', 'vstinner', 'taleinat', 'serhiy.storchaka', 'p-ganssle', 'izbyshev']
    pr_nums = ['8983']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue34481'
    versions = ['Python 3.6', 'Python 3.7', 'Python 3.8']

    Linked PRs

    • gh-52551: Fix encoding issues in strftime() #125193

    Activity

    1. izbyshev commented on Aug 23, 2018

      @izbyshev
      izbyshevmannequin
      on Aug 23, 2018
      MannequinAuthor
      More actions

      The C datetime implementation uses PyUnicode_AsUTF8AndSize() in wrap_strftime() and rejects strings containing surrogate code points (0xD800 - 0xDFFF) since they can't be encoded in UTF-8. On the other hand, the pure-Python datetime implementation doesn't have this restriction:

      >>> import sys
      >>> sys.modules['_datetime'] = None # block C implementation
      >>> from datetime import time
      >>> time().strftime('\ud800')
      '\ud800'
      >>> del sys.modules['datetime']
      >>> del sys.modules['_datetime']
      >>> from datetime import time
      >>> time().strftime('\ud800')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 0: surrogates not allowed
    2. izbyshev
      added
      3.7 (EOL)end of lifeend of life
      3.8 (EOL)end of lifeend of life
      extension-modulesC modules in the Modules dirC modules in the Modules dir
      type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
      on Aug 23, 2018
    3. pganssle commented on Aug 29, 2018

      @pganssle
      pganssle
      on Aug 29, 2018
      Member
      More actions

      I'm finding it very difficult to reconcile these things. I'm not entirely sure, but we may need to take a performance hit in normal strftime if we want to make this work with surrogate characters, which really does not appeal to me (though we can certainly improve to some degree).

      One major question here: Is anyone (@vstinner, @belopolsky?) know why time's strftime opportunistically uses wcsftime instead of strftime? It makes the code *way* more complicated and difficult to read / maintain - are there platforms that provide wcstrftime and not strftime?

      Also, related, it seems according to https://bugs.python.org/issue10653#msg243660 that there may have been a regression in issue bpo-10653, which may be related here.

      Either way, some note should probably be made in the code to clarify exactly *why* these choices were made in the code, in case the situation has changed.

    4. vstinner commented on Aug 29, 2018

      @vstinner
      vstinner
      on Aug 29, 2018
      Member
      More actions

      Because caring of surrogates, I would prefer to first fix time.strftime() and time.strptime() for legit time zone names. Currently, Python uses the C function strfime() because the string produced by wcsftime() cannot be parsed later. We should use the native Windows API to get the time zone name properly encoded. I don't recall the details, sorry. There is maybe an open issue for that one.

    5. vstinner commented on Aug 29, 2018

      @vstinner
      vstinner
      on Aug 29, 2018
      Member
      More actions

      Because caring of surrogates,

      Before*

    6. izbyshev commented on Aug 29, 2018

      @izbyshev
      izbyshevmannequin
      on Aug 29, 2018
      MannequinAuthor
      More actions

      @p-ganssle

      I'm finding it very difficult to reconcile these things.

      Paul, this issue was only about reconciling C and Python implementations of datetime module -- not fixing time.strftime(), which both of them delegate to. While the latter is certainly more important, it's also much more difficult, and IMO needs another issue report (maybe merged with bpo-34512). As for the former, it seems that you've already fixed it in your PR.

    7. pganssle commented on Aug 30, 2018

      @pganssle
      pganssle
      on Aug 30, 2018
      Member
      More actions

      @izbyshev That's totally fair and I wouldn't want to make it a condition of merging the existing fixes - I've already made great progress in fixing the time.strftime part as well.

      The main reason it relates here is that I generally find the tests to be among the hardest part about writing a good PR, and if we can't make assertions about the behavior of strftime outputs, I think it makes it hard to prevent regressions. I figured if I can solve the problem all the way down the stack in one go, I might as well.

      That said, Victor makes an *extremely* good point that this is an outsized effort for the bug it's fixing. No one really *needs* support for unpaired surrogates in their strftime as far as I can tell. The main reason I'm still working on it is that I'm curious to see if it's even possible to fix.

    8. izbyshev commented on Aug 30, 2018

      @izbyshev
      izbyshevmannequin
      on Aug 30, 2018
      MannequinAuthor
      More actions

      if we can't make assertions about the behavior of strftime outputs, I think it makes it hard to prevent regressions.

      Ironically, some of the changes we may have to make to fix time.strftime() inconsistencies may appear like regressions to some users. For example, regarding dropping wcsftime() on all platforms, 'man strftime' on macOS contains the following warning in BUGS section: "The strftime() function does not correctly handle multibyte characters in the format argument.". (I'm not sure what "incorrect handling" means here). That's not to discourage you, just to point out that we should be extra careful at this point when there might be users relying on every variety of the current behavior. And that's also why I don't want to mix the fix for C vs. Python issue (low risk) with changes in time.strftime() (high risk).

      Also, while I certainly agree with "the outsized effort" point, it seems that your PR goes far beyond supporting surrogates because falling back to escaping allows one to bypass checks in wcsftime()/strftime() and round-trip any code point regardless of the current locale.

    9. pganssle commented on Sep 5, 2018

      @pganssle
      pganssle
      on Sep 5, 2018
      Member
      More actions

      I've left a mostly finished PR on bpo-8983, but I've decided it's not really worth continuing to work on. Anyone can feel free to take it and run with it if they want to implement the fix for this.

      As Alexey mentions, that PR indeed already fixes this bug, I mainly blocked on getting consistent behavior across all platforms. Currently that PR has consistent behavior across all platforms if you disable wcsftime *except* Ubuntu 14.0, which seems to have some kind of funky bug in wcstombs, though for the life of me I don't know how to consistently trigger it. I suspect that using strftime instead of wcsftime on all platforms would lead to simpler code that works most consistently, but I am guessing wcsftime is faster.

      Another option is to use wsftime but fall back to strftime on MacOS in the event that the error condition (blank output from non-blank input) is detected.

    10. ezio-melotti
      transferred this issue fromon Apr 10, 2022
    11. serhiy-storchaka
      added this to Date and time issues 🕰️on May 21, 2022
    12. serhiy-storchaka
      self-assigned this
      on Oct 5, 2024
    13. serhiy-storchaka
      added
      3.12only security fixesonly security fixes
      3.13only security fixesonly security fixes
      3.14bugs and security fixesbugs and security fixes
      and removed
      3.8 (EOL)end of lifeend of life
      3.7 (EOL)end of lifeend of life
      on Oct 5, 2024
    14. serhiy-storchaka
      added a commit that references this issue on Oct 9, 2024

      pythongh-52551: Fix encoding issues in strftime()

      c9f1156
    15. serhiy-storchaka
      added 3 commits that reference this issue on Oct 17, 2024

      gh-52551: Fix encoding issues in strftime() (GH-125193)

      ad3eac1

      [3.13] pythongh-52551: Fix encoding issues in strftime() (pythonGH-12…

      13ef787

      pythongh-52551: Fix encoding issues in strftime() (pythonGH-125193)

      4019173
    16. serhiy-storchaka
      closed this as completedon Oct 17, 2024
    17. github-project-automation
      moved this to Done in Date and time issues 🕰️on Oct 17, 2024
    18. serhiy-storchaka
      added a commit that references this issue on Oct 17, 2024

      [3.13] gh-52551: Fix encoding issues in strftime() (GH-125193) (GH-12…

      08ccbb9
    19. miss-islington
      added a commit that references this issue on Oct 17, 2024

      [3.13] pythongh-52551: Fix encoding issues in strftime() (pythonGH-12…

      a34caba
    20. serhiy-storchaka
      added a commit that references this issue on Oct 17, 2024

      [3.12] gh-52551: Fix encoding issues in strftime() (GH-125193) (GH-12…

      232b303
    21. ebonnal
      added a commit that references this issue on Jan 12, 2025

      pythongh-52551: Fix encoding issues in strftime() (pythonGH-125193)

      3a7c158
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    • @serhiy-storchaka
      serhiy-storchaka

    Labels

    3.12only security fixesonly security fixes3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • Date and time issues 🕰️
      Status
      Done
      Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.