@@ -471,4 +471,104 @@ START_TEST(test_multicast_recv_rejects_short_frame)
471471}
472472END_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 */
0 commit comments