From nobody Tue Feb 10 02:46:19 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=swemel.ru ARC-Seal: i=1; a=rsa-sha256; t=1768228495; cv=none; d=zohomail.com; s=zohoarc; b=dOiZkoWzXj34Zl4fbjoEn+fMXR76jXAJztOMDt1tV2Fqi8KWX/bvx1WDPW8F+JtfQggmhQcUoPog1MYvBgF1qQIiyE3AqHRClOLj4MXaR01j9DalPaCootI8XihnY/8xu/6Ca5jHlAnHL1SHAE96XuB1QMTgph5lbXUqTg3ukXY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768228495; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+4Vc8OMcWWcX37Tmnsv38hD9MEh3PyeqecHoWN8Fz1k=; b=ntQAUuHF/lmhcDVfrsx9yIDL2dADdgMPyBD+xHHKIsB+1bPiJEWolbMmHxdGtVmcwXE61+aWnP4uTv5qXPIV35p7RZ4MXtzYCcmmO+piMpGrhLqatnNemUqfOxhdcL0Zz4JZMQt5xucUDmxaT1zQzCAJsnIpzQ0iCWkJvorfycw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1768228488143646.4638411664305; Mon, 12 Jan 2026 06:34:48 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vfIzb-0002f5-Im; Mon, 12 Jan 2026 09:34:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vfIzJ-0002cq-U3 for qemu-devel@nongnu.org; Mon, 12 Jan 2026 09:33:47 -0500 Received: from mx.swemel.ru ([95.143.211.150]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vfIzG-0006n3-Tq for qemu-devel@nongnu.org; Mon, 12 Jan 2026 09:33:45 -0500 From: Dmitry Frolov DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=swemel.ru; s=mail; t=1768228416; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=+4Vc8OMcWWcX37Tmnsv38hD9MEh3PyeqecHoWN8Fz1k=; b=ZFlzUTnkKr1+rmoJ9plLevLH8+jAYdw9gH2hKZb4SdYVASX3t+BtdiZrEZnXBvRb62czY9 GibwREXs8hjk4y1WF4hyTPJWAsAXRhsROnabAhCcycV18dipyL8qN1OXc3VW5/I+mLmKl2 hr7Ove5ajsTGRSxKtR4XyuIlESFUlUo= To: alex.bennee@linaro.org Cc: sdl.qemu@linuxtesting.org, qemu-devel@nongnu.org, Dmitry Frolov Subject: [PATCH] fix NULL-dereference after g_strsplit() Date: Mon, 12 Jan 2026 17:32:09 +0300 Message-Id: <20260112143208.1047235-1-frolov@swemel.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=95.143.211.150; envelope-from=frolov@swemel.ru; helo=mx.swemel.ru X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @swemel.ru) X-ZM-MESSAGEID: 1768228503856158500 Content-Type: text/plain; charset="utf-8" If there is no delimiter in the parsed sting, then the second element (eg.: token[1]) in the returned from the g_strsplit() array will be NULL. When tokens[1] is passed only to qemu_plugin_bool_parse(), no additional check is needed - there is an internal check. Also, there is no need to check tokens and tokens[0] in all mentionaed cases, because argv[i] is guaranteed to be not NULL and delimiter is a string constant (also not NULL). So, g_strsplit() will never return NULL, and the first array element (tokens[0]) will never be NULL. But tokens[1] has to be checked for NULL before usage. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Dmitry Frolov --- contrib/plugins/bbv.c | 2 +- contrib/plugins/cache.c | 24 ++++++++++++------------ contrib/plugins/cflow.c | 2 +- contrib/plugins/drcov.c | 2 +- contrib/plugins/execlog.c | 6 +++--- contrib/plugins/hotpages.c | 6 +++--- contrib/plugins/hwprofile.c | 8 ++++---- contrib/plugins/ips.c | 4 ++-- contrib/plugins/stoptrigger.c | 4 ++-- tests/tcg/plugins/insn.c | 2 +- tests/tcg/plugins/mem.c | 2 +- tests/tcg/plugins/patch.c | 4 ++-- 12 files changed, 33 insertions(+), 33 deletions(-) diff --git a/contrib/plugins/bbv.c b/contrib/plugins/bbv.c index b9da6f815e..b186daf797 100644 --- a/contrib/plugins/bbv.c +++ b/contrib/plugins/bbv.c @@ -132,7 +132,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, for (int i =3D 0; i < argc; i++) { char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); - if (g_strcmp0(tokens[0], "interval") =3D=3D 0) { + if (g_strcmp0(tokens[0], "interval") =3D=3D 0 && tokens[1]) { interval =3D g_ascii_strtoull(tokens[1], NULL, 10); } else if (g_strcmp0(tokens[0], "outfile") =3D=3D 0) { filename =3D tokens[1]; diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c index 56508587d3..c9f818f9d9 100644 --- a/contrib/plugins/cache.c +++ b/contrib/plugins/cache.c @@ -767,29 +767,29 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qe= mu_info_t *info, char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); =20 - if (g_strcmp0(tokens[0], "iblksize") =3D=3D 0) { + if (g_strcmp0(tokens[0], "iblksize") =3D=3D 0 && tokens[1]) { l1_iblksize =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "iassoc") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "iassoc") =3D=3D 0 && tokens[1]) { l1_iassoc =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "icachesize") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "icachesize") =3D=3D 0 && tokens[1= ]) { l1_icachesize =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "dblksize") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "dblksize") =3D=3D 0 && tokens[1])= { l1_dblksize =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "dassoc") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "dassoc") =3D=3D 0 && tokens[1]) { l1_dassoc =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "dcachesize") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "dcachesize") =3D=3D 0 && tokens[1= ]) { l1_dcachesize =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "limit") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "limit") =3D=3D 0 && tokens[1]) { limit =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "cores") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "cores") =3D=3D 0 && tokens[1]) { cores =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "l2cachesize") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "l2cachesize") =3D=3D 0 && tokens[= 1]) { use_l2 =3D true; l2_cachesize =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "l2blksize") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "l2blksize") =3D=3D 0 && tokens[1]= ) { use_l2 =3D true; l2_blksize =3D STRTOLL(tokens[1]); - } else if (g_strcmp0(tokens[0], "l2assoc") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "l2assoc") =3D=3D 0 && tokens[1]) { use_l2 =3D true; l2_assoc =3D STRTOLL(tokens[1]); } else if (g_strcmp0(tokens[0], "l2") =3D=3D 0) { @@ -797,7 +797,7 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu= _info_t *info, fprintf(stderr, "boolean argument parsing failed: %s\n", o= pt); return -1; } - } else if (g_strcmp0(tokens[0], "evict") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "evict") =3D=3D 0 && tokens[1]) { if (g_strcmp0(tokens[1], "rand") =3D=3D 0) { policy =3D RAND; } else if (g_strcmp0(tokens[1], "lru") =3D=3D 0) { diff --git a/contrib/plugins/cflow.c b/contrib/plugins/cflow.c index b5e33f25f9..9db078024a 100644 --- a/contrib/plugins/cflow.c +++ b/contrib/plugins/cflow.c @@ -368,7 +368,7 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu= _info_t *info, for (int i =3D 0; i < argc; i++) { char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); - if (g_strcmp0(tokens[0], "sort") =3D=3D 0) { + if (g_strcmp0(tokens[0], "sort") =3D=3D 0 && tokens[1]) { if (g_strcmp0(tokens[1], "hottest") =3D=3D 0) { report =3D SORT_HOTTEST; } else if (g_strcmp0(tokens[1], "early") =3D=3D 0) { diff --git a/contrib/plugins/drcov.c b/contrib/plugins/drcov.c index 5edc94dcaf..d803231bb6 100644 --- a/contrib/plugins/drcov.c +++ b/contrib/plugins/drcov.c @@ -149,7 +149,7 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu= _info_t *info, { for (int i =3D 0; i < argc; i++) { g_auto(GStrv) tokens =3D g_strsplit(argv[i], "=3D", 2); - if (g_strcmp0(tokens[0], "filename") =3D=3D 0) { + if (g_strcmp0(tokens[0], "filename") =3D=3D 0 && tokens[1]) { file_name =3D g_strdup(tokens[1]); } } diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index 811f320319..7d615b9f3b 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -460,11 +460,11 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugi= n_id_t id, for (int i =3D 0; i < argc; i++) { char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); - if (g_strcmp0(tokens[0], "ifilter") =3D=3D 0) { + if (g_strcmp0(tokens[0], "ifilter") =3D=3D 0 && tokens[1]) { parse_insn_match(tokens[1]); - } else if (g_strcmp0(tokens[0], "afilter") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "afilter") =3D=3D 0 && tokens[1]) { parse_vaddr_match(tokens[1]); - } else if (g_strcmp0(tokens[0], "reg") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "reg") =3D=3D 0 && tokens[1]) { add_regpat(tokens[1]); } else if (g_strcmp0(tokens[0], "rdisas") =3D=3D 0) { if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &disas_assis= t)) { diff --git a/contrib/plugins/hotpages.c b/contrib/plugins/hotpages.c index 9d48ac969e..d6ba8020de 100644 --- a/contrib/plugins/hotpages.c +++ b/contrib/plugins/hotpages.c @@ -171,7 +171,7 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu= _info_t *info, char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", -1); =20 - if (g_strcmp0(tokens[0], "sortby") =3D=3D 0) { + if (g_strcmp0(tokens[0], "sortby") =3D=3D 0 && tokens[1]) { if (g_strcmp0(tokens[1], "reads") =3D=3D 0) { sort_by =3D SORT_R; } else if (g_strcmp0(tokens[1], "writes") =3D=3D 0) { @@ -182,12 +182,12 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qe= mu_info_t *info, fprintf(stderr, "invalid value to sortby: %s\n", tokens[1]= ); return -1; } - } else if (g_strcmp0(tokens[0], "io") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "io") =3D=3D 0 && tokens[1]) { if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &track_io)) { fprintf(stderr, "boolean argument parsing failed: %s\n", o= pt); return -1; } - } else if (g_strcmp0(tokens[0], "pagesize") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "pagesize") =3D=3D 0 && tokens[1])= { page_size =3D g_ascii_strtoull(tokens[1], NULL, 10); } else { fprintf(stderr, "option parsing failed: %s\n", opt); diff --git a/contrib/plugins/hwprofile.c b/contrib/plugins/hwprofile.c index a9838ccc87..cfb031b132 100644 --- a/contrib/plugins/hwprofile.c +++ b/contrib/plugins/hwprofile.c @@ -271,7 +271,7 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu= _info_t *info, char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); =20 - if (g_strcmp0(tokens[0], "track") =3D=3D 0) { + if (g_strcmp0(tokens[0], "track") =3D=3D 0 && tokens[1]) { if (g_strcmp0(tokens[1], "read") =3D=3D 0) { rw =3D QEMU_PLUGIN_MEM_R; } else if (g_strcmp0(tokens[1], "write") =3D=3D 0) { @@ -280,17 +280,17 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qe= mu_info_t *info, fprintf(stderr, "invalid value for track: %s\n", tokens[1]= ); return -1; } - } else if (g_strcmp0(tokens[0], "pattern") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "pattern") =3D=3D 0 && tokens[1]) { if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &pattern)) { fprintf(stderr, "boolean argument parsing failed: %s\n", o= pt); return -1; } - } else if (g_strcmp0(tokens[0], "source") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "source") =3D=3D 0 && tokens[1]) { if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &source)) { fprintf(stderr, "boolean argument parsing failed: %s\n", o= pt); return -1; } - } else if (g_strcmp0(tokens[0], "match") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "match") =3D=3D 0 && tokens[1]) { check_match =3D true; g_string_append_printf(matches_raw, "%s,", tokens[1]); } else { diff --git a/contrib/plugins/ips.c b/contrib/plugins/ips.c index f110c565bc..20de6a8473 100644 --- a/contrib/plugins/ips.c +++ b/contrib/plugins/ips.c @@ -150,7 +150,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, for (int i =3D 0; i < argc; i++) { char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); - if (g_strcmp0(tokens[0], "ips") =3D=3D 0) { + if (g_strcmp0(tokens[0], "ips") =3D=3D 0 && tokens[1]) { char *endptr =3D NULL; max_insn_per_second =3D g_ascii_strtoull(tokens[1], &endptr, 1= 0); if (!max_insn_per_second && errno) { @@ -177,7 +177,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, return -1; } } - } else if (g_strcmp0(tokens[0], "ipq") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "ipq") =3D=3D 0 && tokens[1]) { max_insn_per_quantum =3D g_ascii_strtoull(tokens[1], NULL, 10); =20 if (!max_insn_per_quantum) { diff --git a/contrib/plugins/stoptrigger.c b/contrib/plugins/stoptrigger.c index b3a6ed66a7..733c1f3569 100644 --- a/contrib/plugins/stoptrigger.c +++ b/contrib/plugins/stoptrigger.c @@ -114,7 +114,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, for (int i =3D 0; i < argc; i++) { char *opt =3D argv[i]; g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); - if (g_strcmp0(tokens[0], "icount") =3D=3D 0) { + if (g_strcmp0(tokens[0], "icount") =3D=3D 0 && tokens[1]) { g_auto(GStrv) icount_tokens =3D g_strsplit(tokens[1], ":", 2); icount =3D g_ascii_strtoull(icount_tokens[0], NULL, 0); if (icount < 1 || g_strrstr(icount_tokens[0], "-") !=3D NULL) { @@ -128,7 +128,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, icount_exit_code =3D g_ascii_strtoull(icount_tokens[1], NU= LL, 0); } exit_on_icount =3D true; - } else if (g_strcmp0(tokens[0], "addr") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "addr") =3D=3D 0 && tokens[1]) { g_auto(GStrv) addr_tokens =3D g_strsplit(tokens[1], ":", 2); ExitInfo *ei =3D g_malloc(sizeof(ExitInfo)); ei->exit_addr =3D g_ascii_strtoull(addr_tokens[0], NULL, 0); diff --git a/tests/tcg/plugins/insn.c b/tests/tcg/plugins/insn.c index 0c723cb9ed..190cdae942 100644 --- a/tests/tcg/plugins/insn.c +++ b/tests/tcg/plugins/insn.c @@ -279,7 +279,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, fprintf(stderr, "boolean argument parsing failed: %s\n", o= pt); return -1; } - } else if (g_strcmp0(tokens[0], "match") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "match") =3D=3D 0 && tokens[1]) { parse_match(tokens[1]); } else if (g_strcmp0(tokens[0], "trace") =3D=3D 0) { if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_trace)) { diff --git a/tests/tcg/plugins/mem.c b/tests/tcg/plugins/mem.c index 9649bce99c..d10ff01e75 100644 --- a/tests/tcg/plugins/mem.c +++ b/tests/tcg/plugins/mem.c @@ -338,7 +338,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, fprintf(stderr, "boolean argument parsing failed: %s\n", o= pt); return -1; } - } else if (g_strcmp0(tokens[0], "track") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "track") =3D=3D 0 && tokens[1]) { if (g_strcmp0(tokens[1], "r") =3D=3D 0) { rw =3D QEMU_PLUGIN_MEM_R; } else if (g_strcmp0(tokens[1], "w") =3D=3D 0) { diff --git a/tests/tcg/plugins/patch.c b/tests/tcg/plugins/patch.c index 111c5c1f16..5407f69d12 100644 --- a/tests/tcg/plugins/patch.c +++ b/tests/tcg/plugins/patch.c @@ -208,14 +208,14 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugi= n_id_t id, "Failed to parse boolean argument use_hwaddr\n"); return -1; } - } else if (g_strcmp0(tokens[0], "target") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "target") =3D=3D 0 && tokens[1]) { target_data =3D str_to_bytes(tokens[1]); if (!target_data) { fprintf(stderr, "Failed to parse target bytes.\n"); return -1; } - } else if (g_strcmp0(tokens[0], "patch") =3D=3D 0) { + } else if (g_strcmp0(tokens[0], "patch") =3D=3D 0 && tokens[1]) { patch_data =3D str_to_bytes(tokens[1]); if (!patch_data) { fprintf(stderr, "Failed to parse patch bytes.\n"); --=20 2.34.1