1/* Test ancillary data header creation.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* We use the preprocessor to generate the function/macro tests instead of
20 using indirection because having all the macro expansions alongside
21 each other lets the compiler warn us about suspicious pointer
22 arithmetic across subsequent CMSG_{FIRST,NXT}HDR expansions. */
23
24#include <stdint.h>
25
26#define RUN_TEST_CONCAT(suffix) run_test_##suffix
27#define RUN_TEST_FUNCNAME(suffix) RUN_TEST_CONCAT (suffix)
28
29static void
30RUN_TEST_FUNCNAME (CMSG_NXTHDR_IMPL) (void)
31{
32 struct msghdr m = {0};
33 struct cmsghdr *cmsg;
34 char cmsgbuf[3 * CMSG_SPACE (sizeof (PAYLOAD))] = {0};
35
36 m.msg_control = cmsgbuf;
37 m.msg_controllen = sizeof (cmsgbuf);
38
39 /* First header should point to the start of the buffer. */
40 cmsg = CMSG_FIRSTHDR (&m);
41 TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
42
43 /* If the first header length consumes the entire buffer, there is no
44 space remaining for additional headers. */
45 cmsg->cmsg_len = sizeof (cmsgbuf);
46 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
47 TEST_VERIFY_EXIT (cmsg == NULL);
48
49 /* The first header length is so big, using it would cause an overflow. */
50 cmsg = CMSG_FIRSTHDR (&m);
51 TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
52 cmsg->cmsg_len = SIZE_MAX;
53 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
54 TEST_VERIFY_EXIT (cmsg == NULL);
55
56 /* The first header leaves just enough space to hold another header. */
57 cmsg = CMSG_FIRSTHDR (&m);
58 TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
59 cmsg->cmsg_len = sizeof (cmsgbuf) - sizeof (struct cmsghdr);
60 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
61 TEST_VERIFY_EXIT (cmsg != NULL);
62
63 /* The first header leaves space but not enough for another header. */
64 cmsg = CMSG_FIRSTHDR (&m);
65 TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
66 cmsg->cmsg_len ++;
67 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
68 TEST_VERIFY_EXIT (cmsg == NULL);
69
70 /* The second header leaves just enough space to hold another header. */
71 cmsg = CMSG_FIRSTHDR (&m);
72 TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
73 cmsg->cmsg_len = CMSG_LEN (sizeof (PAYLOAD));
74 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
75 TEST_VERIFY_EXIT (cmsg != NULL);
76 cmsg->cmsg_len = sizeof (cmsgbuf)
77 - CMSG_SPACE (sizeof (PAYLOAD)) /* First header. */
78 - sizeof (struct cmsghdr);
79 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
80 TEST_VERIFY_EXIT (cmsg != NULL);
81
82 /* The second header leaves space but not enough for another header. */
83 cmsg = CMSG_FIRSTHDR (&m);
84 TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
85 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
86 TEST_VERIFY_EXIT (cmsg != NULL);
87 cmsg->cmsg_len ++;
88 cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
89 TEST_VERIFY_EXIT (cmsg == NULL);
90
91 return;
92}
93

source code of glibc/socket/tst-cmsghdr-skeleton.c