Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2218152/?format=api
{ "id": 2218152, "url": "http://patchwork.ozlabs.org/api/patches/2218152/?format=api", "web_url": "http://patchwork.ozlabs.org/project/glibc/patch/20260331133626.260355-1-gaoxiang@kylinos.cn/", "project": { "id": 41, "url": "http://patchwork.ozlabs.org/api/projects/41/?format=api", "name": "GNU C Library", "link_name": "glibc", "list_id": "libc-alpha.sourceware.org", "list_email": "libc-alpha@sourceware.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260331133626.260355-1-gaoxiang@kylinos.cn>", "list_archive_url": null, "date": "2026-03-31T13:35:10", "name": "[v2] libio: Fix wide stream backup buffer leak on fclose [BZ #33999]", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "ce9f37ca05db6a1306b7fb2d5638082f4dbc66c9", "submitter": { "id": 92909, "url": "http://patchwork.ozlabs.org/api/people/92909/?format=api", "name": "Gao Xiang", "email": "gaoxiang@kylinos.cn" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/glibc/patch/20260331133626.260355-1-gaoxiang@kylinos.cn/mbox/", "series": [ { "id": 498199, "url": "http://patchwork.ozlabs.org/api/series/498199/?format=api", "web_url": "http://patchwork.ozlabs.org/project/glibc/list/?series=498199", "date": "2026-03-31T13:35:10", "name": "[v2] libio: Fix wide stream backup buffer leak on fclose [BZ #33999]", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/498199/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2218152/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2218152/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "libc-alpha@sourceware.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "libc-alpha@sourceware.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n dmarc=none (p=none dis=none) header.from=kylinos.cn", "sourceware.org; spf=pass smtp.mailfrom=kylinos.cn", "server2.sourceware.org;\n arc=none smtp.remote-ip=124.126.103.232" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4flTgh5C3Jz1yGH\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 01 Apr 2026 00:37:15 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 9ED4E4BA23E5\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 13:37:13 +0000 (GMT)", "from mailgw.kylinos.cn (mailgw.kylinos.cn [124.126.103.232])\n by sourceware.org (Postfix) with ESMTPS id 4F4074BA2E17\n for <libc-alpha@sourceware.org>; Tue, 31 Mar 2026 13:36:51 +0000 (GMT)", "from fedora [(183.242.174.21)] by mailgw.kylinos.cn\n (envelope-from <gaoxiang@kylinos.cn>)\n (Generic MTA with TLSv1.3 TLS_AES_256_GCM_SHA384 256/256)\n with ESMTP id 1877483175; Tue, 31 Mar 2026 21:36:39 +0800" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 9ED4E4BA23E5", "OpenDKIM Filter v2.11.0 sourceware.org 4F4074BA2E17" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 4F4074BA2E17", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 4F4074BA2E17", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774964212; cv=none;\n b=g6yz67TeatjjqEWoI6GsrieTWwWzVilUPPeU8m5BHuu0vsh80wTa3CG/sReWJOuShovKRCOmWBoa1TAoRwZze3WSXYTlv72OVj11o15UFqa9VbAIDhNIZ/l6NLW5TR997K61jY/SINSNYBuXwF/FbM/DEkWL/NMF7Y7IeJQNllQ=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774964212; c=relaxed/simple;\n bh=kymg674CX5XoaatoMCNLDDohDb7ptGp9ZuDMGXZUxCI=;\n h=From:To:Subject:Date:Message-ID:MIME-Version;\n b=nV0C+1xoSL6EdNyegMDZr1zrmjomwrp0MGd8jGTCMRtRX3IMN/nCtBXnj0fkOvZoPUaphHvU9/f4PJuJA0tiSNSB92YsgSWyK/kXXbCkAD/uwH4pqjYvUUXTBHZV8dlRPyFIEvkr+yWSc7ufseWjp9CAVJJgyqWXARXL1hQi9vk=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "X-UUID": [ "a5b42b362d0611f1aa26b74ffac11d73-20260331", "a5b42b362d0611f1aa26b74ffac11d73-20260331" ], "X-CTIC-Tags": "HR_CC_COUNT, HR_CC_DOMAIN_COUNT, HR_CC_NAME, HR_CTE_8B,\n HR_CTT_TXT\n HR_DATE_H, HR_DATE_WKD, HR_DATE_ZONE, HR_FROM_NAME,\n HR_SJ_DIGIT_LEN\n HR_SJ_LANG, HR_SJ_LEN, HR_SJ_LETTER, HR_SJ_NOR_SYM, HR_SJ_PHRASE\n HR_SJ_PHRASE_LEN, HR_SJ_WS, HR_TO_COUNT, HR_TO_DOMAIN_COUNT, HR_TO_NO_NAME\n IP_TRUSTED, SRC_TRUSTED, DN_TRUSTED, SA_TRUSTED, SA_EXISTED\n SN_TRUSTED, SN_EXISTED, SPF_NOPASS, DKIM_NOPASS, DMARC_NOPASS\n UD_TRUSTED, CIE_BAD, CIE_GOOD, CIE_GOOD_SPF, GTI_FG_BS\n GTI_C_CI, GTI_FG_IT, GTI_RG_INFO, GTI_C_BU, AMN_GOOD\n ABX_BLACK, ABX_EXPLOIT, ABX_MISS_RDNS", "X-CID-O-RULE": "Release_Ham", "X-CID-RULE": "Release_Ham", "X-CID-O-INFO": "VERSION:1.3.12, REQID:626e96c1-1c46-4412-878c-20e743c1cbf5,\n IP:10,\n URL:0,TC:0,Content:0,EDM:0,RT:0,SF:-5,FILE:0,BULK:0,RULE:Release_Ham,ACTIO\n N:release,TS:5", "X-CID-INFO": "VERSION:1.3.12, REQID:626e96c1-1c46-4412-878c-20e743c1cbf5, IP:10,\n UR\n L:0,TC:0,Content:0,EDM:0,RT:0,SF:-5,FILE:0,BULK:0,RULE:Release_Ham,ACTION:\n release,TS:5", "X-CID-META": "VersionHash:e7bac3a, CLOUDID:bdacb0de4e08b6e461548e8fd0a78fe8,\n BulkI\n D:260331213642KR2NCZX8,BulkQuantity:0,Recheck:0,SF:17|19|66|78|102|127|898\n ,TC:nil,Content:0|15|50,EDM:-3,IP:-2,URL:99|1,File:nil,RT:nil,Bulk:nil,QS:\n nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,AR\n C:0", "X-CID-BVR": "2,SSN|SDN", "X-CID-BAS": "2,SSN|SDN,0,_", "X-CID-FACTOR": "TF_CID_SPAM_ULS,TF_CID_SPAM_SNR,TF_CID_SPAM_FAS,TF_CID_SPAM_FSD", "X-CID-RHF": "D41D8CD98F00B204E9800998ECF8427E", "X-User": "gaoxiang@kylinos.cn", "From": "Gao Xiang <gaoxiang@kylinos.cn>", "To": "libc-alpha@sourceware.org", "Cc": "Andreas Schwab <schwab@suse.de>,\n\tXiang Gao <gaoxiang@kylinos.cn>", "Subject": "[PATCH v2] libio: Fix wide stream backup buffer leak on fclose [BZ\n #33999]", "Date": "Tue, 31 Mar 2026 21:35:10 +0800", "Message-ID": "<20260331133626.260355-1-gaoxiang@kylinos.cn>", "X-Mailer": "git-send-email 2.53.0", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "libc-alpha@sourceware.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Libc-alpha mailing list <libc-alpha.sourceware.org>", "List-Unsubscribe": "<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>", "List-Archive": "<https://sourceware.org/pipermail/libc-alpha/>", "List-Post": "<mailto:libc-alpha@sourceware.org>", "List-Help": "<mailto:libc-alpha-request@sourceware.org?subject=help>", "List-Subscribe": "<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>", "Errors-To": "libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org" }, "content": "From: Xiang Gao <gaoxiang@kylinos.cn>\n\nThis patch fixes a memory leak when ungetwc is used on a wide oriented stream,\nThe backup buffer was never freed on fclose, causing a memory leak per\nungetwc/fclose call.\n\nThe leak has two causes:\n\nIn iofclose.c, for wide streams (fp->mode > 0), _IO_new_fclose never calls\n_IO_free_wbackup_area. Fixed by adding the missing call.\n\nIn wgenops.c, _IO_wdefault_finish checks fp->_IO_save_base (the narrow field,\nalways NULL for wide streams) instead of fp->_wide_data->_IO_save_base,\nand uses a bare free() that leaves _IO_save_end and _IO_backup_base dangling.\nReplace the hand-rolled cleanup with _IO_hava_wbackup/_IO_free_wbackup_area,\nwhich handles backup-mode switching and clears all three pointers.\n\nThis was independently reported by Rocket Ma [1], whose patch corrects the condition\nbut still uses the manual free path.\n\nApply the same _IO_hava_backup condition in genops.c for consistency.\n\nTested by:\nmake test t=libio/tst-wbackup-leak\n\n[1] https://patchwork.sourceware.org/project/glibc/patch/20260323171742.1039768-1-marocketbd@gmail.com/\n\nSigned-off-by: Xiang Gao <gaoxiang@kylinos.cn>\n---\nThank you for the review.\n\nChanges since v1:\n - Use _IO_have_backup / _IO_have_wbackup as conditions.\n - Keeps wmemstream in the test: Agreed that ungetwc on a wmemstream is not\n a valid application use.However I was unable to trigger the backup buffer\n allocation through a tmpfile-based read/ungetwc sequence.\n Using wmemstream route is the most direct way to reach the leaking code in\n _IO_wdefault_finish. Open to suggestions if you know a cleaner way to trigger it.\n---\n libio/Makefile | 1 +\n libio/genops.c | 7 ++-----\n libio/iofclose.c | 7 +++++--\n libio/tst-wbackup-leak.c | 45 ++++++++++++++++++++++++++++++++++++++++\n libio/wgenops.c | 7 ++-----\n 5 files changed, 55 insertions(+), 12 deletions(-)\n create mode 100644 libio/tst-wbackup-leak.c", "diff": "diff --git a/libio/Makefile b/libio/Makefile\nindex 08e1e0ec25..93656466df 100644\n--- a/libio/Makefile\n+++ b/libio/Makefile\n@@ -135,6 +135,7 @@ tests = \\\n tst-swscanf \\\n tst-ungetwc1 \\\n tst-ungetwc2 \\\n+ tst-wbackup-leak \\\n tst-wfile-sync \\\n tst-wfiledoallocate-static \\\n tst-widetext \\\ndiff --git a/libio/genops.c b/libio/genops.c\nindex cc1684e00a..90e08e6571 100644\n--- a/libio/genops.c\n+++ b/libio/genops.c\n@@ -636,11 +636,8 @@ _IO_default_finish (FILE *fp, int dummy)\n for (mark = fp->_markers; mark != NULL; mark = mark->_next)\n mark->_sbuf = NULL;\n \n- if (fp->_IO_save_base)\n- {\n- _IO_free_backup_buf (fp, fp->_IO_save_base);\n- fp->_IO_save_base = NULL;\n- }\n+ if (_IO_have_backup (fp))\n+ _IO_free_backup_area (fp);\n \n _IO_un_link ((struct _IO_FILE_plus *) fp);\n \ndiff --git a/libio/iofclose.c b/libio/iofclose.c\nindex 89782e99d7..3d1ee3e3cb 100644\n--- a/libio/iofclose.c\n+++ b/libio/iofclose.c\n@@ -67,8 +67,11 @@ _IO_new_fclose (FILE *fp)\n _IO_FINISH (fp);\n if (fp->_mode > 0)\n {\n+ if (fp->_wide_data->_IO_save_base)\n+ _IO_free_wbackup_area (fp);\n+\n /* This stream has a wide orientation. This means we have to free\n-\t the conversion functions. */\n+ the conversion functions. */\n struct _IO_codecvt *cc = fp->_codecvt;\n \n __libc_lock_lock (__gconv_lock);\n@@ -79,7 +82,7 @@ _IO_new_fclose (FILE *fp)\n else\n {\n if (_IO_have_backup (fp))\n-\t_IO_free_backup_area (fp);\n+ _IO_free_backup_area (fp);\n }\n _IO_deallocate_file (fp);\n return status;\ndiff --git a/libio/tst-wbackup-leak.c b/libio/tst-wbackup-leak.c\nnew file mode 100644\nindex 0000000000..c5bf128237\n--- /dev/null\n+++ b/libio/tst-wbackup-leak.c\n@@ -0,0 +1,45 @@\n+/* Test _IO_wdefault_finish frees wide backup buffer [BZ #33999]. */\n+\n+#include <malloc.h>\n+#include <stdio.h>\n+#include <wchar.h>\n+#include <support/check.h>\n+\n+static void\n+one_round (void)\n+{\n+ wchar_t *buf = NULL;\n+ size_t size = 0;\n+\n+ FILE *fp = open_wmemstream (&buf, &size);\n+ TEST_VERIFY_EXIT (fp != NULL);\n+ fputwc (L'A', fp);\n+ fflush (fp);\n+ /*·Push·back·without·prior·read.··read_ptr·==·read_base,·so\n+···*··_IO_wdefault_pbackfail·skips·the·buggy·narrow·read_ptr·access\n+···*··(BZ·#33998)·and·goes·straight·to·allocating·a·wide·backup\n+ ·*··buffer·at·fp->_wide_data->_IO_save_base.··*/\n+ ungetwc (L'Z', fp);\n+ fclose (fp);\n+ free (buf);\n+}\n+\n+static int\n+do_test (void)\n+{\n+ /* Warm up to stabilize allocator state.*/\n+ one_round ();\n+\n+ struct mallinfo2 before = mallinfo2 ();\n+ for (int i = 0; i < 1000; i++)\n+ one_round ();\n+ struct mallinfo2 after = mallinfo2 ();\n+\n+ /* Each leak is 128 * sizeof(wchar_t) = 512 bytes.\n+ * 1000 iterations would leak ~512 KB. Allow 4 KB noise. */\n+ TEST_VERIFY (after.uordblks - before.uordblks < 4096);\n+\n+ return 0;\n+}\n+\n+#include <support/test-driver.c>\ndiff --git a/libio/wgenops.c b/libio/wgenops.c\nindex 064d71266d..6829477e0c 100644\n--- a/libio/wgenops.c\n+++ b/libio/wgenops.c\n@@ -181,11 +181,8 @@ _IO_wdefault_finish (FILE *fp, int dummy)\n for (mark = fp->_markers; mark != NULL; mark = mark->_next)\n mark->_sbuf = NULL;\n \n- if (fp->_IO_save_base)\n- {\n- free (fp->_wide_data->_IO_save_base);\n- fp->_IO_save_base = NULL;\n- }\n+ if (_IO_have_wbackup (fp))\n+ _IO_free_wbackup_area (fp);\n \n #ifdef _IO_MTSAFE_IO\n if (fp->_lock != NULL)\n", "prefixes": [ "v2" ] }