python / python/cpython

Musl libc strftime for format strings ending in %

オープン
#127,527 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

extension-modules OS-unsupported type-bug
主要言語
Python
スター
77.2k
フォーク
35.9k
PR マージ指標
PR 指標を取得中

説明

In glibc if the format string ends in %, strftime and wcsftime will turn it into a %. In musl libc, if the format string ends in %, both wcsftime and strftime return 0 with errno 0 and leave random stuff in the buffer. There's no way for us to distinguish between this and "out of space" without looking at the format string. The following 7 character patch would fix musl to behave the same as glibc:

--- a/src/time/strftime.c
+++ b/src/time/strftime.c
@@ -225,7 +225,7 @@ size_t __strftime_l(char *restrict s, size_t n, const char
*restrict f, const st
 			s[l] = 0;
 			return l;
		}
-		if (*f != '%') {
+		if (*f != '%' || !f[1]) {
 			s[l++] = *f;
 			continue;
 		}

but it sounds like musl may be against applying this patch because it is their position that the behavior is undefined? See this thread:
https://www.openwall.com/lists/musl/2022/12/19/3

So in this case, we repeatedly get format_string returning 0 and end up here:
https://github.com/python/cpython/blob/main/Modules/timemodule.c?plain=1#L844
Then if HAVE_WCSFTIME we call PyUnicode_FromWideChar(*outbuf, 0) which notices we're making an empty string and returns here:
https://github.com/python/cpython/blob/main/Objects/unicodeobject.c?plain=1#L2004-L2005
On the other hand, if !HAVE_WCSFTIME we call PyUnicode_DecodeLocaleAndSize which checks if str[len] != '\0' and raises ValueError("Embedded null byte") here:
https://github.com/python/cpython/blob/main/Objects/unicodeobject.c?plain=1#L4004

So what to do? Well for one thing, it seems to me that we can tell whether format_time is trying to return an empty string by checking if the string ends in a null byte as it should e.g., *outbuf[buflen] == 0. This can allow us to be a bit more conservative in time_strftime1.

Linked PRs
  • gh-127528

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

Modules/timemodule.c、特に time_strftime1 とその format_time の処理から始め、次に musl の src/time/strftime.c について説明されている動作と比較します。time.strftime を通じて末尾に % があるケースを再現し、リンクされている PR gh-127528 を確認します。プラットフォーム依存の結果が一貫して処理され、空でないバッファを空文字列として扱わないことが完了の条件です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
c, python
領域
operating-systems
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
30/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。