[From nobody Sat Aug  1 16:21:05 2026
Received: (at submit) by bugs.debian.org; 23 Jul 2026 21:45:01 +0000
X-Spam-Checker-Version: SpamAssassin 4.0.1-bugs.debian.org_2005_01_02
 (2024-03-25) on buxtehude.debian.org
X-Spam-Level: 
X-Spam-Status: No, score=-19.1 required=4.0 tests=BAYES_00,
 BODY_INCLUDES_PACKAGE,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,
 DKIM_VALID_EF,FOURLA,HAS_PACKAGE,MD5_SHA1_SUM,SPF_HELO_PASS,SPF_PASS,
 WORD_WITHOUT_VOWELS,XMAILER_REPORTBUG autolearn=ham autolearn_force=no
 version=4.0.1-bugs.debian.org_2005_01_02
X-Spam-Bayes: score:0.0000 Tokens: new, 79; hammy, 148; neutral, 113; spammy,
 2. spammytokens:0.993-+--Terms, 0.987-1--hsh
 hammytokens:0.000-+--H*Ad:N*Bug, 0.000-+--H*Ad:N*Tracking,
 0.000-+--HTo:N*Debian, 0.000-+--HTo:N*System, 0.000-+--HTo:N*Bug
Return-path: &lt;e@80x24.org&gt;
Received: from dcvr.yhbt.net ([173.255.242.215]:33192)
 by buxtehude.debian.org with esmtps
 (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256)
 (Exim 4.96) (envelope-from &lt;e@80x24.org&gt;) id 1wn1Dw-00EGbM-2Y
 for submit@bugs.debian.org; Thu, 23 Jul 2026 21:45:01 +0000
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org;
 s=selector1; t=1784843099;
 bh=h2yvllZnx3uQimS21cyu/RE+v+hoQaoXSXXeXwUqERI=;
 h=From:To:Subject:Date:From;
 b=kR+D0HSvFFLIVE7K8zAV2sVDqYwje2fWtCf4pR7E5duRjYwE5quo5/ugJWwhIxQrj
 ZpBicMr36U47mr/teBZvt5K7QB0+k4UHfzQ0+ATl0qFl0RIpA2dUEiZzeNjuB4KH06
 1Bjf443IGp4XXRGroZzgzJRKB/KGFMxh4LLj5bfQ=
Received: by dcvr.yhbt.net (Postfix, from userid 1000)
 id B16491F49B; Thu, 23 Jul 2026 21:44:59 +0000 (UTC)
Content-Type: multipart/mixed; boundary=&quot;===============1035798137==&quot;
MIME-Version: 1.0
From: Eric Wong &lt;e@80x24.org&gt;
To: Debian Bug Tracking System &lt;submit@bugs.debian.org&gt;
Subject: libsocket-msghdr-perl: recvmsg fails to set flags (.msg_flags)
Message-ID: &lt;178484309960.5069.15924260826770070324.reportbug@dcvr.yhbt.net&gt;
X-Mailer: reportbug 12.0.0
Date: Thu, 23 Jul 2026 21:44:59 +0000
Delivered-To: submit@bugs.debian.org

This is a multi-part MIME message sent by reportbug.


--===============1035798137==
Content-Type: text/plain; charset=&quot;us-ascii&quot;
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Package: libsocket-msghdr-perl
Version: 0.05-2+b4
Severity: normal
Tags: patch upstream

Dear Maintainer,

recvmsg in Socket::MsgHdr fails to set the `flags' value to
what the recvmsg(2) syscall writes to `struct msghdr'.msg_flags.

This makes it impossible to detect truncation errors such as
MSG_TRUNC and MSG_CTRUNC when the `buflen' and `controllen'
fields are too small.  Attached is a patch which fixes the
issue in upstream.

Unfortunately, I cannot contribute directly to upstream due to
Terms of Service and JS requirement of Github causing
accessibility problems.

--===============1035798137==
Content-Type: text/plain; charset=&quot;us-ascii&quot;
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=&quot;0001-recvmsg-set-flags-field-according-to-.msg_flags.patch&quot;

&gt;From af9d3624155ab51cd752f27981ef3b7287d24153 Mon Sep 17 00:00:00 2001
From: Eric Wong &lt;e@80x24.org&gt;
Date: Thu, 23 Jul 2026 20:54:15 +0000
Subject: [PATCH] recvmsg: set `flags' field according to .msg_flags

The .msg_flags field of `struct msghdr' gets populated by the
recvmsg(2) syscall.  Most notably, .msg_flags allows the
receiver to detect truncation via MSG_TRUNC and MSG_CTRUNC flags
when the supplied `buflen' and/or `controllen' fields are too
small.

Note that MSG_TRUNC set in .msg_flags by recvfrom is different
from the `flags' argument.  MSG_TRUNC in the `flags' argument
changes the return value of recvfrom(2) to the intended length
of the data, whereas .msg_flags merely tells the caller the
buffer is too small and does not tell the intended length.

MSG_TRUNC in the `flags' argument probably makes the most sense
with MSG_PEEK, as shown in the below example to dynamically
size `buflen' to the necessary value to avoid MSG_TRUNC in
.msg_flags in a subsequent recvmsg call:

  use Socket;
  use Socket::MsgHdr;
  my ($rd, $wr);
  socketpair($rd, $wr, AF_UNIX, SOCK_DGRAM, 0) or die &quot;socketpair: $!&quot;;
  my $hdr = Socket::MsgHdr-&gt;new(buf =&gt; 'ab');
  sendmsg($wr, $hdr, 0) or die &quot;sendmsg: $!&quot;;
  my $m = Socket::MsgHdr-&gt;new(buflen =&gt; 1);
  my $r = recvmsg($rd, $m, MSG_TRUNC|MSG_PEEK) or die &quot;recvmsg: $!&quot;;
  print &quot;MSG_TRUNC=&quot;, MSG_TRUNC, &quot;\n&quot;;
  print &quot;before: r=$r flags=&quot;, $m-&gt;flags,
        &quot; (expecting (flags &amp; MSG_TRUNC=${\MSG_TRUNC}))\n&quot;;
  $m = Socket::MsgHdr-&gt;new(buflen =&gt; $r);
  recvmsg($rd, $m, 0) or die &quot;recvmsg: $!&quot;;
  print &quot; after: r=$r flags=&quot;, $m-&gt;flags, &quot; (expecting flags==0)\n&quot;;
---
 MsgHdr.xs  |  4 ++++
 t/30recv.t | 40 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/MsgHdr.xs b/MsgHdr.xs
index 0e4b932..9b7123a 100644
--- a/MsgHdr.xs
+++ b/MsgHdr.xs
@@ -158,6 +158,10 @@ smh_recvmsg(s, msg_hdr, flags = 0)
             SvCUR_set(*svp, RETVAL);
         if ((svp = hv_fetch(hsh, &quot;control&quot;, 7, FALSE)))
             SvCUR_set(*svp, mh.m.msg_controllen);
+        if ((svp = hv_fetch(hsh, &quot;flags&quot;, 5, FALSE))) {
+            SvUPGRADE(*svp, SVt_IV);
+            SvIV_set(*svp, mh.m.msg_flags);
+        }
     }
     OUTPUT:
     RETVAL
diff --git a/t/30recv.t b/t/30recv.t
index 7bb2b8e..c12daa4 100644
--- a/t/30recv.t
+++ b/t/30recv.t
@@ -6,7 +6,7 @@
 # change 'tests =&gt; 1' to 'tests =&gt; last_test_to_print';
 
 use Test::More;
-BEGIN { plan tests =&gt; 9 };
+BEGIN { plan tests =&gt; 11 };
 use bytes;
 use strict;
 use Socket;
@@ -124,4 +124,42 @@ SKIP: {
 
   cmp_ok($dev1, '==', $dev2, &quot;scm_rights fds on same device&quot;);
   cmp_ok($ino1, '==', $ino2, &quot;scm_rights fds are same inode&quot;);
+
+  eval { &amp;MSG_CTRUNC; }; # autoloaded, may not be defined yet
+  skip &quot;msg_ctrunc not defined&quot;, 1 if $@;
+
+  socketpair(Rd, Wr, AF_UNIX, SOCK_DGRAM, 0)
+    or die &quot;socketpair: $!\n&quot;;
+
+  $hdr = new Socket::MsgHdr(buf =&gt; &quot;hello!&quot;);
+  $hdr-&gt;cmsghdr(SOL_SOCKET, SCM_RIGHTS, pack('i', fileno STDIN));
+  sendmsg(\*Wr, $hdr, 0)
+    or die &quot;sendmsg: $!\n&quot;;
+
+  $m = new Socket::MsgHdr(buflen =&gt; 256, controllen =&gt; 1);
+  recvmsg(\*Rd, $m, 0)
+    or die &quot;recvmsg: $!\n&quot;;
+
+  ok($m-&gt;flags &amp; MSG_CTRUNC, 'MSG_CTRUNC set when controllen is too short');
+
+  close Rd; close Wr;
+};
+
+# 11
+SKIP: {
+  local (*Rd, *Wr);
+  socketpair(Rd, Wr, AF_UNIX, SOCK_DGRAM, 0)
+    or die &quot;socketpair: $!\n&quot;;
+
+  my $hdr = new Socket::MsgHdr(buf =&gt; 'ab');
+  sendmsg(\*Wr, $hdr, 0)
+    or die &quot;sendmsg: $!\n&quot;;
+
+  my $m = new Socket::MsgHdr(buflen =&gt; 1);
+  recvmsg(\*Rd, $m, 0)
+    or die &quot;recvmsg: $!\n&quot;;
+
+  ok($m-&gt;flags &amp; MSG_TRUNC, 'MSG_TRUNC set when buflen is too short');
+
+  close Rd; close Wr;
 };

--===============1035798137==--
]