@@ -36,13 +36,16 @@ typedef struct {
3636 struct sockaddr_storage raddr ;
3737} request_t ;
3838
39- static int is_ipv4_address (char * str ) {
39+ static int is_ipv4_address (const char * str ) {
4040 struct in6_addr addr ;
4141 return inet_pton (AF_INET , str , & addr ) == 1 ;
4242}
4343
4444static int hostname_from_url (const char * url_in ,
4545 char * hostname , const size_t hostname_len ) {
46+ if (!url_in || !hostname || hostname_len == 0 ) {
47+ return 0 ;
48+ }
4649 int res = 0 ;
4750 CURLU * url = curl_url ();
4851 if (url != NULL ) {
@@ -54,8 +57,9 @@ static int hostname_from_url(const char* url_in,
5457 if (rc == CURLUE_OK && host_len < hostname_len &&
5558 host [0 ] != '[' && host [host_len - 1 ] != ']' && // skip IPv6 address
5659 !is_ipv4_address (host )) {
57- strncpy (hostname , host , hostname_len - 1 ); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
58- hostname [hostname_len - 1 ] = '\0' ;
60+ size_t copy_len = host_len < hostname_len - 1 ? host_len : hostname_len - 1 ;
61+ memcpy (hostname , host , copy_len );
62+ hostname [copy_len ] = '\0' ;
5963 res = 1 ; // success
6064 }
6165 curl_free (host );
@@ -80,10 +84,11 @@ static void sigpipe_cb(struct ev_loop __attribute__((__unused__)) *loop,
8084
8185static void https_resp_cb (void * data , char * buf , size_t buflen ) {
8286 request_t * req = (request_t * )data ;
83- DLOG ("Received response for id: %hX, len: %zu" , req -> tx_id , buflen );
8487 if (req == NULL ) {
85- FLOG ("%04hX: data NULL" , req -> tx_id );
88+ FLOG ("data NULL in https_resp_cb" );
89+ return ;
8690 }
91+ DLOG ("Received response for id: %hX, len: %zu" , req -> tx_id , buflen );
8792 free ((void * )req -> dns_req );
8893 if (buf != NULL ) { // May be NULL for timeout, DNS failure, or something similar.
8994 if (buflen < (int )sizeof (uint16_t )) {
@@ -107,6 +112,11 @@ static void https_resp_cb(void *data, char *buf, size_t buflen) {
107112static void dns_server_cb (dns_server_t * dns_server , void * data ,
108113 struct sockaddr * addr , uint16_t tx_id ,
109114 char * dns_req , size_t dns_req_len ) {
115+ if (!dns_server || !data || !addr || !dns_req ) {
116+ ELOG ("NULL pointer in dns_server_cb" );
117+ if (dns_req ) free (dns_req );
118+ return ;
119+ }
110120 app_state_t * app = (app_state_t * )data ;
111121
112122 DLOG ("Received request for id: %hX, len: %d" , tx_id , dns_req_len );
@@ -139,34 +149,63 @@ static void dns_server_cb(dns_server_t *dns_server, void *data,
139149}
140150
141151static int addr_list_reduced (const char * full_list , const char * list ) {
152+ if (!full_list || !list ) {
153+ return 1 ;
154+ }
155+
142156 const char * pos = list ;
143- const char * end = list + strlen (list );
157+ const size_t list_len = strlen (list );
158+ const char * end = list + list_len ;
159+
144160 while (pos < end ) {
145- char current [50 ];
161+ char current [INET6_ADDRSTRLEN ];
146162 const char * comma = strchr (pos , ',' );
147- size_t ip_len = comma ? comma - pos : end - pos ;
148- strncpy (current , pos , ip_len ); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
163+ size_t ip_len = comma ? (size_t )(comma - pos ) : (size_t )(end - pos );
164+
165+ if (ip_len == 0 || ip_len >= sizeof (current )) {
166+ DLOG ("Invalid IP address length: %zu" , ip_len );
167+ return 1 ;
168+ }
169+
170+ memcpy (current , pos , ip_len );
149171 current [ip_len ] = '\0' ;
150172
151- const char * match_begin = strstr (full_list , current );
152- if (!match_begin ||
153- !(match_begin == full_list || * (match_begin - 1 ) == ',' ) ||
154- !(* (match_begin + ip_len ) == ',' || * (match_begin + ip_len ) == '\0' )) {
173+ // More efficient search: check if the current IP exists as a complete token
174+ const char * search_pos = full_list ;
175+ int found = 0 ;
176+
177+ while ((search_pos = strstr (search_pos , current )) != NULL ) {
178+ // Check if it's a complete token (preceded and followed by delimiter or boundary)
179+ int is_start = (search_pos == full_list || * (search_pos - 1 ) == ',' );
180+ int is_end = (* (search_pos + ip_len ) == ',' || * (search_pos + ip_len ) == '\0' );
181+
182+ if (is_start && is_end ) {
183+ found = 1 ;
184+ break ;
185+ }
186+ search_pos += ip_len ;
187+ }
188+
189+ if (!found ) {
155190 DLOG ("IP address missing: %s" , current );
156191 return 1 ;
157192 }
158193
159- pos += ip_len + 1 ;
194+ pos = comma ? comma + 1 : end ;
160195 }
161196 return 0 ;
162197}
163198
164199static void dns_poll_cb (const char * hostname , void * data ,
165200 const char * addr_list ) {
201+ if (!hostname || !data || !addr_list ) {
202+ ELOG ("NULL pointer in dns_poll_cb" );
203+ return ;
204+ }
166205 app_state_t * app = (app_state_t * )data ;
167206 char buf [255 + (sizeof (":443:" ) - 1 ) + POLLER_ADDR_LIST_SIZE ];
168207 memset (buf , 0 , sizeof (buf )); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
169- if (strlen (hostname ) > 254 ) { FLOG ("Hostname too long." ); }
208+ if (strlen (hostname ) > 253 ) { FLOG ("Hostname too long." ); }
170209 int ip_start = snprintf (buf , sizeof (buf ) - 1 , "%s:443:" , hostname ); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
171210 (void )snprintf (buf + ip_start , sizeof (buf ) - 1 - ip_start , "%s" , addr_list ); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
172211 if (app -> resolv && app -> resolv -> data ) {
@@ -205,7 +244,7 @@ static int proxy_supports_name_resolution(const char *proxy)
205244 return 0 ;
206245}
207246
208- static const char * sw_version (void ) {
247+ static const char * sw_version (void ) {
209248#ifdef SW_VERSION
210249 return SW_VERSION ;
211250#else
@@ -315,10 +354,27 @@ int main(int argc, char *argv[]) {
315354 }
316355
317356 if (opt .daemonize ) {
318- // daemon() is non-standard. If needed, see OpenSSH openbsd-compat/daemon.c
319- if (daemon (0 , 0 ) == -1 ) {
320- FLOG ("daemon failed: %s" , strerror (errno ));
357+ // Use fork() and setsid() instead of deprecated daemon()
358+ pid_t pid = fork ();
359+ if (pid < 0 ) {
360+ FLOG ("fork failed: %s" , strerror (errno ));
361+ } else if (pid > 0 ) {
362+ exit (0 ); // parent exits
363+ }
364+
365+ if (setsid () < 0 ) {
366+ FLOG ("setsid failed: %s" , strerror (errno ));
321367 }
368+
369+ // Change working directory to root
370+ if (chdir ("/" ) < 0 ) {
371+ FLOG ("chdir failed: %s" , strerror (errno ));
372+ }
373+
374+ // Close standard file descriptors
375+ close (STDIN_FILENO );
376+ close (STDOUT_FILENO );
377+ close (STDERR_FILENO );
322378 }
323379
324380 ev_signal sigpipe ;
0 commit comments