Re: Chasing a segfault, part II

2021-10-27 Thread miim
 

After two days of testing I can testify that Sorin's analysis is correct. 
Sometimes Apache points to a user-agent string, sometimes it points to a null 
string, and sometimes there is a null pointer.

The reason nothing appeared in the logs is because the requests coming in with 
empty user-agent headers were going to the default server, not to one of the 
named vhosts. The default server returns 410 on everything and logs nothing. 
The test module should not have been active on the default server, but it is a 
good thing it was; this would have been wretched if it had gone to the field 
with that bug.

For future reference to anyone dealing with the user-agent string, here is the 
code I adopted which handles all three possibilities. It is streamlined from 
the original version and no longer copies the user-agent string to local 
storage. This allows the CRC and DJB2 routines to process the entire string and 
not a length-limited substring.


size_t ualength;
const unsigned char* uastring;

...
...

 /* Retrieve the user-agent string */

 uastring = apr_table_get(r->headers_in, "User-Agent");

 /* If there is no user-agent string, the CRC/DJB2 defaults to x/x0 */

 ua_crc = 0x;
 ua_djb = 0x0;

 /* If the user-agent string is empty, the CRC/DJB2 defaults to x0/x. */

 if (uastring != NULL) {
 ua_crc = 0x0;
 ua_djb = 0x;
 ualength = strlen(uastring);

 /* If user-agent string exists, compute the CRC-32 and DJB2 hash */

 if (ualength != 0) {
 ua_crc = bc_crc_32(r, bc_scfg, uastring, ualength);
 ua_djb = bc_djb2hash(r, bc_scfg, uastring, ualength);
 }
 }


My thanks to everyone who commented on the problem. I would not have found the 
issue without assistance.

 On Tuesday, 26 October 2021, 07:59:04 am GMT+1, Sorin Manolache 
 wrote:  
 
 On 26/10/2021 08.18, miim wrote:
> ua_pointer = apr_table_get(r->headers_in, "User-Agent");
>        /* Find out how long the Apache-supplied string is */
>    ualength = strlen(ua_pointer);

If the request does not contain any user-agent then ua_pointer will be 
NULL. strlen of NULL will segfault.

S
  

Re: Chasing a segfault, part II

2021-10-26 Thread Sorin Manolache

On 26/10/2021 08.18, miim wrote:

ua_pointer = apr_table_get(r->headers_in, "User-Agent");
   /* Find out how long the Apache-supplied string is */
   ualength = strlen(ua_pointer);


If the request does not contain any user-agent then ua_pointer will be 
NULL. strlen of NULL will segfault.


S


Chasing a segfault, part II

2021-10-26 Thread miim


My thanks to everyone for their input on this problem.  While I was unable to 
get the backtrace and whatkilledus modules to report on failure, I isolated the 
cause to the following code in the handler.

The code itself does not segfault and indeed it appears to execute properly, 
retrieving the user-agent string with correct length and logging it.  However, 
when this code is included Apache segfaults some time later.  (It's not the 
logging causing it; the segfault still occurs without the logging.)

I can not see why this code should be overwriting Apache data structures in 
such a way as to cause Apache to segfault.  I have rewritten it several 
different ways and it still causes segfaults.

Might anyone have insight into this issue?


== HANDLER CODE ==

static int bridcheck_handler
   (request_rec *r) {

  const char *ua_pointer;
  char useragent[UA_BUFFERSIZE];
  size_t ualength;
  size_t ualen2;

  /* Retrieve the user-agent string */

  /* Null the last byte in our buffer so that strings are always terminated 
*/
  useragent[UA_BUFFERSIZE-1] = '\0';
  /* Load pointer to the Apache request record user-agent header field */
  ua_pointer = apr_table_get(r->headers_in, "User-Agent");
  /* Find out how long the Apache-supplied string is */
  ualength = strlen(ua_pointer);
  /* Copy only if there's something to copy */
  if (ualength != 0)
  /* Our buffer gets Apache's request record user-agent field */
  /* Protect from segfault by limiting length at buffersize -1 */
strncpy(useragent, ua_pointer, UA_BUFFERSIZE-1);
  /* Don't use the original strncpy below.  Dissected the functionality 
into pieces above. */
  /*  strncpy(useragent, apr_table_get(r->headers_in, "User-Agent"), 
UA_BUFFERSIZE-1); */
  /* Now that we have our prize ... how long is it? */
  ualen2 = strlen(useragent);

  ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
  "bc: ualength = %u, <%s>",
  ualength, apr_table_get(r->headers_in, "User-Agent"));
  ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
  "ualen2   = %u, <%s>",
  ualen2, useragent);

  return DECLINED;

  }

== ERROR LOG EXTRACT 

Oct 26 05:10:39  157.55.39.67  bc: ualength = 71, http://www.bing.com/bingbot.htm)>
Oct 26 05:10:39  157.55.39.67  ualen2   = 71, http://www.bing.com/bingbot.htm)>
Oct 26 05:11:11  71.6.232.7  bc: ualength = 115, 
Oct 26 05:11:11  71.6.232.7  ualen2   = 115, 
Oct 26 05:17:33  110.70.47.92  bc: ualength = 120, 
Oct 26 05:17:33  110.70.47.92  ualen2   = 120,