Skip to content

Commit f9982fd

Browse files
committed
Addressed two more copilot's comments.
1 parent 6792420 commit f9982fd

3 files changed

Lines changed: 127 additions & 12 deletions

File tree

src/test/unit/unit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ Suite *wolf_suite(void)
238238
tcase_add_test(tc_utils, test_multicast_if_pins_egress_interface);
239239
tcase_add_test(tc_utils, test_multicast_loop_does_not_fire_on_blocked_send);
240240
tcase_add_test(tc_utils, test_multicast_recv_rejects_short_frame);
241+
tcase_add_test(tc_utils, test_multicast_setsockopt_accepts_unaligned_mreq);
242+
tcase_add_test(tc_utils, test_multicast_getsockopt_ttl_loop_accepts_uint8);
241243
#endif
242244
tcase_add_test(tc_utils, test_tcp_no_rst_for_broadcast_dst);
243245
tcase_add_test(tc_utils, test_tcp_no_rst_for_multicast_dst);

src/test/unit/unit_tests_multicast.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,4 +471,104 @@ START_TEST(test_multicast_recv_rejects_short_frame)
471471
}
472472
END_TEST
473473

474+
START_TEST(test_multicast_setsockopt_accepts_unaligned_mreq)
475+
{
476+
struct wolfIP s;
477+
int sd;
478+
/* 1 byte of padding before the mreq so the struct lands at odd alignment
479+
* even on strict-alignment toolchains. A direct (const struct *)cast on
480+
* this pointer would be an unaligned uint32_t load; UBSAN
481+
* -fsanitize=alignment flags that as undefined behaviour. */
482+
uint8_t raw[1 + sizeof(struct wolfIP_ip_mreq)];
483+
struct wolfIP_ip_mreq mreq_native;
484+
uint8_t raw_if[1 + sizeof(struct wolfIP_mreq_addr)];
485+
struct wolfIP_mreq_addr if_native;
486+
ip4 group = 0xE9010209U;
487+
ip4 iface_ip = 0x0A000002U;
488+
489+
wolfIP_init(&s);
490+
mock_link_init(&s);
491+
wolfIP_ipconfig_set(&s, iface_ip, 0xFFFFFF00U, 0);
492+
sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
493+
ck_assert_int_gt(sd, 0);
494+
495+
/* IP_ADD_MEMBERSHIP via a misaligned mreq. */
496+
multicast_mreq(&mreq_native, group, IPADDR_ANY);
497+
memset(raw, 0, sizeof(raw));
498+
memcpy(raw + 1, &mreq_native, sizeof(mreq_native));
499+
ck_assert_int_eq(wolfIP_sock_setsockopt(&s, sd, WOLFIP_SOL_IP,
500+
WOLFIP_IP_ADD_MEMBERSHIP, raw + 1,
501+
(socklen_t)sizeof(mreq_native)), 0);
502+
ck_assert_uint_eq(s.mcast[0].refs, 1);
503+
504+
/* IP_DROP_MEMBERSHIP via a misaligned mreq. */
505+
memset(raw, 0, sizeof(raw));
506+
memcpy(raw + 1, &mreq_native, sizeof(mreq_native));
507+
ck_assert_int_eq(wolfIP_sock_setsockopt(&s, sd, WOLFIP_SOL_IP,
508+
WOLFIP_IP_DROP_MEMBERSHIP, raw + 1,
509+
(socklen_t)sizeof(mreq_native)), 0);
510+
ck_assert_uint_eq(s.mcast[0].refs, 0);
511+
512+
/* IP_MULTICAST_IF via a misaligned wolfIP_mreq_addr. */
513+
if_native.s_addr = ee32(iface_ip);
514+
memset(raw_if, 0, sizeof(raw_if));
515+
memcpy(raw_if + 1, &if_native, sizeof(if_native));
516+
ck_assert_int_eq(wolfIP_sock_setsockopt(&s, sd, WOLFIP_SOL_IP,
517+
WOLFIP_IP_MULTICAST_IF, raw_if + 1,
518+
(socklen_t)sizeof(if_native)), 0);
519+
ck_assert_uint_eq(s.udpsockets[SOCKET_UNMARK(sd)].sock.udp.mcast_if_set, 1);
520+
}
521+
END_TEST
522+
523+
START_TEST(test_multicast_getsockopt_ttl_loop_accepts_uint8)
524+
{
525+
struct wolfIP s;
526+
int sd;
527+
int ttl_in = 7;
528+
int loop_in = 0;
529+
uint8_t byte_buf;
530+
int int_buf;
531+
socklen_t len;
532+
533+
wolfIP_init(&s);
534+
mock_link_init(&s);
535+
wolfIP_ipconfig_set(&s, 0x0A000002U, 0xFFFFFF00U, 0);
536+
sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
537+
ck_assert_int_gt(sd, 0);
538+
ck_assert_int_eq(wolfIP_sock_setsockopt(&s, sd, WOLFIP_SOL_IP,
539+
WOLFIP_IP_MULTICAST_TTL, &ttl_in, sizeof(ttl_in)), 0);
540+
ck_assert_int_eq(wolfIP_sock_setsockopt(&s, sd, WOLFIP_SOL_IP,
541+
WOLFIP_IP_MULTICAST_LOOP, &loop_in, sizeof(loop_in)), 0);
542+
543+
/* getsockopt with a uint8_t buffer must succeed and write one byte,
544+
* mirroring setsockopt which already accepts either size. */
545+
byte_buf = 0xff;
546+
len = sizeof(byte_buf);
547+
ck_assert_int_eq(wolfIP_sock_getsockopt(&s, sd, WOLFIP_SOL_IP,
548+
WOLFIP_IP_MULTICAST_TTL, &byte_buf, &len), 0);
549+
ck_assert_uint_eq(len, sizeof(byte_buf));
550+
ck_assert_uint_eq(byte_buf, 7U);
551+
552+
byte_buf = 0xff;
553+
len = sizeof(byte_buf);
554+
ck_assert_int_eq(wolfIP_sock_getsockopt(&s, sd, WOLFIP_SOL_IP,
555+
WOLFIP_IP_MULTICAST_LOOP, &byte_buf, &len), 0);
556+
ck_assert_uint_eq(len, sizeof(byte_buf));
557+
ck_assert_uint_eq(byte_buf, 0U);
558+
559+
/* The larger int path still works and returns sizeof(int). */
560+
int_buf = -1;
561+
len = sizeof(int_buf);
562+
ck_assert_int_eq(wolfIP_sock_getsockopt(&s, sd, WOLFIP_SOL_IP,
563+
WOLFIP_IP_MULTICAST_TTL, &int_buf, &len), 0);
564+
ck_assert_uint_eq(len, sizeof(int_buf));
565+
ck_assert_int_eq(int_buf, 7);
566+
567+
/* Zero-length buffer is still rejected. */
568+
len = 0;
569+
ck_assert_int_eq(wolfIP_sock_getsockopt(&s, sd, WOLFIP_SOL_IP,
570+
WOLFIP_IP_MULTICAST_TTL, &byte_buf, &len), -WOLFIP_EINVAL);
571+
}
572+
END_TEST
573+
474574
#endif /* IP_MULTICAST */

src/wolfip.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6329,17 +6329,20 @@ int wolfIP_sock_setsockopt(struct wolfIP *s, int sockfd, int level, int optname,
63296329
if (level == WOLFIP_SOL_IP && IS_SOCKET_UDP(sockfd)) {
63306330
if (optname == WOLFIP_IP_ADD_MEMBERSHIP ||
63316331
optname == WOLFIP_IP_DROP_MEMBERSHIP) {
6332-
const struct wolfIP_ip_mreq *mreq =
6333-
(const struct wolfIP_ip_mreq *)optval;
6332+
struct wolfIP_ip_mreq mreq;
63346333
unsigned int if_idx;
63356334
ip4 group;
63366335
ip4 if_addr;
63376336
int ret;
63386337

6339-
if (!mreq || optlen < (socklen_t)sizeof(*mreq))
6338+
/* Copy into an aligned local to avoid unaligned 32-bit loads on
6339+
* strict-alignment targets when the caller's optval buffer is
6340+
* not naturally aligned. */
6341+
if (!optval || optlen < (socklen_t)sizeof(mreq))
63406342
return -WOLFIP_EINVAL;
6341-
group = ee32(mreq->imr_multiaddr.s_addr);
6342-
if_addr = ee32(mreq->imr_interface.s_addr);
6343+
memcpy(&mreq, optval, sizeof(mreq));
6344+
group = ee32(mreq.imr_multiaddr.s_addr);
6345+
if_addr = ee32(mreq.imr_interface.s_addr);
63436346
ret = mcast_if_from_addr(s, if_addr, group, &if_idx);
63446347
if (ret < 0)
63456348
return ret;
@@ -6348,15 +6351,15 @@ int wolfIP_sock_setsockopt(struct wolfIP *s, int sockfd, int level, int optname,
63486351
return udp_mcast_drop(s, ts, group, if_idx);
63496352
}
63506353
if (optname == WOLFIP_IP_MULTICAST_IF) {
6351-
const struct wolfIP_mreq_addr *addr =
6352-
(const struct wolfIP_mreq_addr *)optval;
6354+
struct wolfIP_mreq_addr addr;
63536355
unsigned int if_idx;
63546356
ip4 if_addr;
63556357
int ret;
63566358

6357-
if (!addr || optlen < (socklen_t)sizeof(*addr))
6359+
if (!optval || optlen < (socklen_t)sizeof(addr))
63586360
return -WOLFIP_EINVAL;
6359-
if_addr = ee32(addr->s_addr);
6361+
memcpy(&addr, optval, sizeof(addr));
6362+
if_addr = ee32(addr.s_addr);
63606363
/* Linux IP_MULTICAST_IF with INADDR_ANY clears the pinned
63616364
* interface and reverts to per-destination routing. */
63626365
if (if_addr == IPADDR_ANY) {
@@ -6499,12 +6502,22 @@ int wolfIP_sock_getsockopt(struct wolfIP *s, int sockfd, int level, int optname,
64996502
optname == WOLFIP_IP_MULTICAST_LOOP) {
65006503
int value;
65016504

6502-
if (!optval || !optlen || *optlen < (socklen_t)sizeof(int))
6505+
if (!optval || !optlen || *optlen < (socklen_t)sizeof(uint8_t))
65036506
return -WOLFIP_EINVAL;
65046507
value = (optname == WOLFIP_IP_MULTICAST_TTL) ?
65056508
ts->sock.udp.mcast_ttl : ts->sock.udp.mcast_loop;
6506-
memcpy(optval, &value, sizeof(value));
6507-
*optlen = sizeof(value);
6509+
/* Linux get_ip_sockopt writes IP_MULTICAST_TTL/LOOP as int when
6510+
* the caller provided room for one and as a single byte when the
6511+
* buffer is exactly sizeof(uint8_t) — keeps get/set symmetric
6512+
* with setsockopt, which accepts either width. */
6513+
if (*optlen >= (socklen_t)sizeof(value)) {
6514+
memcpy(optval, &value, sizeof(value));
6515+
*optlen = sizeof(value);
6516+
} else {
6517+
uint8_t value8 = (uint8_t)value;
6518+
memcpy(optval, &value8, sizeof(value8));
6519+
*optlen = sizeof(value8);
6520+
}
65086521
return 0;
65096522
}
65106523
if (optname == WOLFIP_IP_MULTICAST_IF) {

0 commit comments

Comments
 (0)