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 — gh-111089: PyUnicode_AsUTF8() now raises on embedded NUL by vstinner · Pull Request #111091 · python/cpython

Conversation

@vstinner

@vstinner vstinner commented Oct 20, 2023 •
edited by github-actions Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member
  • PyUnicode_AsUTF8() now raises an exception if the string contains embedded null characters.
  • PyUnicode_AsUTF8AndSize() now sets *size to 0 on error to avoid undefined variable value.
  • Update related C API tests (test_capi.test_unicode).
  • type_new_set_doc() uses PyUnicode_AsUTF8AndSize() to silently truncate doc containing null bytes.
  • Issue: [C API] Change PyUnicode_AsUTF8() to return NULL on embedded null characters #111089

📚 Documentation preview 📚: https://cpython-previews--111091.org.readthedocs.build/

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@vstinner
vstinner requested a review from markshannon as a code owner October 20, 2023 00:02
@bedevere-app bedevere-app Bot mentioned this pull request Oct 20, 2023
[C API] Change PyUnicode_AsUTF8() to return NULL on embedded null characters #111089
Closed
@bedevere-app bedevere-app Bot added the awaiting core review label Oct 20, 2023
@vstinner

vstinner commented Oct 20, 2023

Copy link
Copy Markdown
Member Author

cc @serhiy-storchaka

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

vstinner
vstinner commented Oct 20, 2023
View reviewed changes
Comment thread Objects/unicodeobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

serhiy-storchaka
serhiy-storchaka reviewed Oct 20, 2023
View reviewed changes

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered this idea when added such checks in other functions, but at that time PyUnicode_AsUTF8() was rather a simple accessor to internal data.

Most sites where it matters where changed to use PyUnicode_AsUTF8AndSize() + strlen(). Now some of them can be changed back to use PyUnicode_AsUTF8().

Do you consider to include PyUnicode_AsUTF8() in the limited C API?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Include/cpython/unicodeobject.h
extracted from the returned data.
*/

// Returns a pointer to the default encoding (UTF-8) of the

@serhiy-storchaka serhiy-storchaka Oct 20, 2023

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it necessary to change the type of the comment? Most comments here are /* */.

It makes reviewing the changes more difficult.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Oct 20, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not necessary, but I take this PR as an opportunity to change the comment style. IMO multi-line comments written with // comment syntax are way easier to read.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/unicodeobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Oct 20, 2023

Copy link
Copy Markdown
Member Author

Do you consider to include PyUnicode_AsUTF8() in the limited C API?

It's my main motivation for this change. It's the most natural way to get a char*. But I prefer to discuss it separetely.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
pythongh-111089: PyUnicode_AsUTF8() now raises on embedded NUL
4e0b3d3
* PyUnicode_AsUTF8() now raises an exception if the string contains
  embedded null characters.
* Update related C API tests (test_capi.test_unicode).
* type_new_set_doc() uses PyUnicode_AsUTF8AndSize() to silently
  truncate doc containing null bytes.
@vstinner
vstinner force-pushed the asutf8 branch from 91e159c to 4e0b3d3 Compare October 20, 2023 10:04
@vstinner

vstinner commented Oct 20, 2023

Copy link
Copy Markdown
Member Author

Most sites where it matters where changed to use PyUnicode_AsUTF8AndSize() + strlen(). Now some of them can be changed back to use PyUnicode_AsUTF8().

Once this change will be merged, we can review PyUnicode_AsUTF8() and PyUnicode_AsUTF8AndSize() usage. But I chose to make this PR as small to possible to ease the review.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

serhiy-storchaka
serhiy-storchaka reviewed Oct 20, 2023
View reviewed changes
Comment thread Objects/unicodeobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner @serhiy-storchaka
Update Objects/unicodeobject.c
957c433
Co-authored-by: Serhiy Storchaka <[email protected]>
@vstinner

vstinner commented Oct 20, 2023

Copy link
Copy Markdown
Member Author

Oh. It seems like I removed the cast fix in my latest change. Thanks @serhiy-storchaka, I applied your suggestion.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

serhiy-storchaka
serhiy-storchaka approved these changes Oct 20, 2023
View reviewed changes
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels Oct 20, 2023
@serhiy-storchaka

serhiy-storchaka commented Oct 20, 2023

Copy link
Copy Markdown
Member

But why set size to 0, and not to -1? There is larger chance to miss error. For example PyUnicode_FromStringAndSize(NULL, 0) and PyBytes_FromStringAndSize(NULL, 0) return empty string and empty bytes object, but if size is negative, they raise exception.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Oct 20, 2023

Copy link
Copy Markdown
Member Author

But why set size to 0, and not to -1?

Is this comment related to my PyUnicode_AsUTF8AndSize change, PR #111106?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@serhiy-storchaka

serhiy-storchaka commented Oct 20, 2023

Copy link
Copy Markdown
Member

Yes.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
vstinner merged commit d731579 into python:main Oct 20, 2023
@vstinner
vstinner deleted the asutf8 branch October 20, 2023 15:59
@bedevere-app bedevere-app Bot removed the awaiting merge label Oct 20, 2023
@vstinner

vstinner commented Oct 20, 2023

Copy link
Copy Markdown
Member Author

Merged, thanks for the review @serhiy-storchaka.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner vstinner mentioned this pull request Oct 20, 2023
gh-111089: Add PyUnicode_AsUTF8() to the limited C API #111121
Merged
@vstinner vstinner mentioned this pull request Nov 1, 2023
gh-111089: Add cache to PyUnicode_AsUTF8() for embedded NUL #111587
Closed
@Yhg1s

Yhg1s commented Nov 2, 2023

Copy link
Copy Markdown
Member

Is this change really necessary? Are there any examples of this actually being a problem? How common are the problematic patterns in actual user code?

Why is recommending a replacement of PyUnicode_AsUTF8AndSize(s, NULL) any better than leaving PyUnicode_AsUTF8(s) as-is? Considering the two have been documented and recommended as alternatives for so long, is it a good idea to break the equivalence? How should users know that one is "safe" and the other is not?

I use PyUnicode_AsUTF8() in performance-critical situations, and the extra check is wholly unnecessary for my uses. I'm also concerned about the change of semantics. Here's at least one simple example that would cause user code to start failing: creating a string with PyUnicode_FromUTF8AndSize() and passing buffer size instead of string length, then later fetching the data with PyUnicode_AsUTF8().

JelleZijlstra, zooba, and hauntsaninja reacted with thumbs up emoji
All reactions
  • 👍 3 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Nov 2, 2023

Copy link
Copy Markdown
Member Author

I use PyUnicode_AsUTF8() in performance-critical situations, and the extra check is wholly unnecessary for my uses.

I wrote PR #111587 to avoid calling strlen() in most cases.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s

Yhg1s commented Nov 2, 2023

Copy link
Copy Markdown
Member

I wrote PR #111587 to avoid calling strlen() in most cases.

Caching the result does not affect my use-cases.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Nov 2, 2023

Copy link
Copy Markdown
Member Author

Caching the result does not affect my use-cases.

Can you please add a comment on PR #111587 to explain why your use case is not covered by the cache?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Nov 2, 2023

Copy link
Copy Markdown
Member Author

Is this change really necessary? Are there any examples of this actually being a problem? How common are the problematic patterns in actual user code?

Sorry, I made the assumption that the background of this change was a common knowledge. I wrote issue #111656 to describe the issue.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Nov 2, 2023

Copy link
Copy Markdown
Member Author

Here's at least one simple example that would cause user code to start failing: creating a string with PyUnicode_FromUTF8AndSize() and passing buffer size instead of string length, then later fetching the data with PyUnicode_AsUTF8().

If the string does not contain embedded null character, the code continues to work. But if it contains null characters, right, you now get an exception. In that case, you should use PyUnicode_AsUTF8AndSize(), PyUnicode_AsUTF8String() or any other existing API which returns the size of the UTF-8 encoded string (and don't raise an exception in case of embedded null character).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s

Yhg1s commented Nov 2, 2023

Copy link
Copy Markdown
Member

Caching the result does not affect my use-cases.

Can you please add a comment on PR #111587 to explain why your use case is not covered by the cache?

I've commented there, but just for clarity: it's because it only ever calls PyUnicode_AsUTF8() once per string.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s

Yhg1s commented Nov 2, 2023

Copy link
Copy Markdown
Member

Here's at least one simple example that would cause user code to start failing: creating a string with PyUnicode_FromUTF8AndSize() and passing buffer size instead of string length, then later fetching the data with PyUnicode_AsUTF8().

If the string does not contain embedded null character, the code continues to work. But if it contains null characters, right, you now get an exception. In that case, you should use PyUnicode_AsUTF8AndSize(), PyUnicode_AsUTF8String() or any other existing API which returns the size of the UTF-8 encoded string (and don't raise an exception in case of embedded null character).

This is exactly the problem I'm pointing out. You are breaking existing code because you're making bad assumptions. The assumption is that the user didn't check for NULs before, or that handling NULs this way would be problematic. It does not have to be. You're forcing users who are correctly using the API to use a different API for no reason other than to signal to you that they're using it correctly. If users don't care about the length of the returned string, and they don't care about embedded NULs, why would they have to change anything? You're just introducing churn here.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Nov 2, 2023

Copy link
Copy Markdown
Member Author

If users don't care about the length of the returned string, and they don't care about embedded NULs, why would they have to change anything? You're just introducing churn here.

Using PyUnicode_AsUTF8() instead of PyUnicode_AsUTF8AndSize() doesn't mean that you don't care about the length. You can use PyUnicode_AsUTF8() when you use any C API which expects a null terminated string. strlen() gives you the string length, but you don't need to explicitly pass the length, the null terminator is used for that.

I'm not sure that PyUnicode_AsUTF8() implies that you don't care about embedded null characters.

Would you mind to elaborate how you create a string with null characters and then truncate the string at the first null character on purpose? What does the string contain? Why not truncating at null when you create the string? Do you have examples of code doing that?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner vstinner mentioned this pull request Nov 3, 2023
gh-111089: Add PyUnicode_AsUTF8Unsafe() function #111672
Closed
vstinner added a commit to vstinner/cpython that referenced this pull request Nov 7, 2023
@vstinner
Revert "pythongh-111089: PyUnicode_AsUTF8() now raises on embedded NUL (
be7e341
python#111091)"

This reverts commit d731579.
@vstinner vstinner mentioned this pull request Nov 7, 2023
gh-111089: Revert PyUnicode_AsUTF8() changes #111833
Merged
vstinner added a commit that referenced this pull request Nov 7, 2023
@vstinner
gh-111089: Revert PyUnicode_AsUTF8() changes (#111833)
11e8348
* Revert "gh-111089: Use PyUnicode_AsUTF8() in Argument Clinic (#111585)"

This reverts commit d9b606b.

* Revert "gh-111089: Use PyUnicode_AsUTF8() in getargs.c (#111620)"

This reverts commit cde1071.

* Revert "gh-111089: PyUnicode_AsUTF8() now raises on embedded NUL (#111091)"

This reverts commit d731579.

* Revert "gh-111089: Add PyUnicode_AsUTF8() to the limited C API (#111121)"

This reverts commit d8f32be.

* Revert "gh-111089: Use PyUnicode_AsUTF8() in sqlite3 (#111122)"

This reverts commit 37e4e20.
hugovk pushed a commit to hugovk/cpython that referenced this pull request Nov 8, 2023
@vstinner @hugovk
pythongh-111089: Revert PyUnicode_AsUTF8() changes (python#111833)
7fca996
* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in Argument Clinic (python#111585)"

This reverts commit d9b606b.

* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in getargs.c (python#111620)"

This reverts commit cde1071.

* Revert "pythongh-111089: PyUnicode_AsUTF8() now raises on embedded NUL (python#111091)"

This reverts commit d731579.

* Revert "pythongh-111089: Add PyUnicode_AsUTF8() to the limited C API (python#111121)"

This reverts commit d8f32be.

* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in sqlite3 (python#111122)"

This reverts commit 37e4e20.
aisk pushed a commit to aisk/cpython that referenced this pull request Feb 11, 2024
@vstinner @serhiy-storchaka @aisk
pythongh-111089: PyUnicode_AsUTF8() now raises on embedded NUL (pytho…
6f3024f
…n#111091)

* PyUnicode_AsUTF8() now raises an exception if the string contains
  embedded null characters.
* Update related C API tests (test_capi.test_unicode).
* type_new_set_doc() uses PyUnicode_AsUTF8AndSize() to silently
  truncate doc containing null bytes.

Co-authored-by: Serhiy Storchaka <[email protected]>
aisk pushed a commit to aisk/cpython that referenced this pull request Feb 11, 2024
@vstinner @aisk
pythongh-111089: Revert PyUnicode_AsUTF8() changes (python#111833)
fce855e
* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in Argument Clinic (python#111585)"

This reverts commit d9b606b.

* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in getargs.c (python#111620)"

This reverts commit cde1071.

* Revert "pythongh-111089: PyUnicode_AsUTF8() now raises on embedded NUL (python#111091)"

This reverts commit d731579.

* Revert "pythongh-111089: Add PyUnicode_AsUTF8() to the limited C API (python#111121)"

This reverts commit d8f32be.

* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in sqlite3 (python#111122)"

This reverts commit 37e4e20.
Glyphack pushed a commit to Glyphack/cpython that referenced this pull request Sep 2, 2024
@vstinner @serhiy-storchaka @Glyphack
pythongh-111089: PyUnicode_AsUTF8() now raises on embedded NUL (pytho…
af7fb2a
…n#111091)

* PyUnicode_AsUTF8() now raises an exception if the string contains
  embedded null characters.
* Update related C API tests (test_capi.test_unicode).
* type_new_set_doc() uses PyUnicode_AsUTF8AndSize() to silently
  truncate doc containing null bytes.

Co-authored-by: Serhiy Storchaka <[email protected]>
Glyphack pushed a commit to Glyphack/cpython that referenced this pull request Sep 2, 2024
@vstinner @Glyphack
pythongh-111089: Revert PyUnicode_AsUTF8() changes (python#111833)
455f5c7
* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in Argument Clinic (python#111585)"

This reverts commit d9b606b.

* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in getargs.c (python#111620)"

This reverts commit cde1071.

* Revert "pythongh-111089: PyUnicode_AsUTF8() now raises on embedded NUL (python#111091)"

This reverts commit d731579.

* Revert "pythongh-111089: Add PyUnicode_AsUTF8() to the limited C API (python#111121)"

This reverts commit d8f32be.

* Revert "pythongh-111089: Use PyUnicode_AsUTF8() in sqlite3 (python#111122)"

This reverts commit 37e4e20.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@serhiy-storchaka serhiy-storchaka serhiy-storchaka approved these changes
@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@vstinner @serhiy-storchaka @Yhg1s
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.