@@ -98,10 +98,9 @@ off_t dhcp_close_options(dhcp_packet_t *pkt, off_t off)
9898bool packet::decode ()
9999{
100100 unsigned char *limit = (unsigned char *) packet_ + length;
101-
102101 unsigned char *opt = (unsigned char *) &packet_->options ;
103102
104- if (length <= DHCP_FIXED_NON_UDP )
103+ if (length < DHCP_FIXED_NON_UDP + 4 )
105104 {
106105 fprintf (stderr, " dhcpcd: Bad packet length %zu, ignoring!\n " , length);
107106 return false ;
@@ -116,27 +115,50 @@ bool packet::decode()
116115 bool has_message_type = false ;
117116
118117 opt += 4 ;
119- while (* opt != DHO_END )
118+ while (opt < limit )
120119 {
121- /* Check for OOB */
122- if (opt >= limit)
120+ unsigned char type = *opt, optlen;
121+
122+ if (type == DHO_PAD )
123123 {
124- fprintf (stderr, " dhcpcd: Went out of bounds processing options, ignoring! \n " ) ;
125- return false ;
124+ opt++ ;
125+ continue ;
126126 }
127127
128- unsigned char type = *opt;
128+ if (type == DHO_END )
129+ break ;
130+ /* Check if the length member fits */
131+ if (opt + 1 >= limit)
132+ goto oob;
129133 opt++;
130- unsigned char length = *opt;
134+ optlen = *opt;
135+
136+ /* Check if the option actually fits */
137+ if (opt + 1 + optlen > limit)
138+ goto oob;
139+
140+ /* No option with a "length" can be 0-sized. This also implicitly makes it so
141+ * has_message_type = true means get_option(DHO_DHCP_MESSAGE_TYPE) succeeds. */
142+ if (!optlen)
143+ {
144+ fprintf (stderr, " dhcpcd: Bad 0-length option, ignoring!\n " );
145+ return false ;
146+ }
131147
132148 if (type == DHO_DHCP_MESSAGE_TYPE )
133149 has_message_type = true ;
134150
135- dhcp_option option{opt + 1 , type, length};
136-
151+ dhcp_option option{opt + 1 , type, optlen};
137152 options.push_back (std::move (option));
153+ opt = opt + optlen + 1 ;
154+ }
138155
139- opt = opt + length + 1 ;
156+ /* Check for OOB */
157+ if (opt >= limit)
158+ {
159+ oob:
160+ fprintf (stderr, " dhcpcd: Went out of bounds processing options, ignoring!\n " );
161+ return false ;
140162 }
141163
142164 if (!has_message_type)
0 commit comments