@@ -428,55 +428,62 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
428
428
}
429
429
430
430
apr_status_t modsecurity_request_body_to_stream (modsec_rec * msr , const char * buffer , int buflen , char * * error_msg ) {
431
- char * stream_input_body = NULL ;
432
- char * data = NULL ;
433
- int first_pkt = 0 ;
431
+ apr_size_t allocate ;
432
+ char * allocated ;
434
433
435
- if (msr -> stream_input_data == NULL ) {
436
- msr -> stream_input_data = (char * )calloc (sizeof (char ), msr -> stream_input_length + 1 );
437
- first_pkt = 1 ;
438
- }
439
- else {
440
-
441
- data = (char * )malloc (msr -> stream_input_length + 1 - buflen );
434
+ if (msr -> stream_input_data == NULL ) {
435
+ // Is the request body length is known beforehand? (requests that are not Transfer-Encoding: chunked)
436
+ if (msr -> request_content_length > 0 ) {
437
+ allocate = msr -> request_content_length ;
438
+ }
439
+ else {
440
+ // We don't know how this request is going to be, so hope for just buflen to begin with (requests that are Transfer-Encoding: chunked)
441
+ allocate = buflen ;
442
+ }
442
443
443
- if (data == NULL )
444
+ allocated = (char * ) calloc (allocate , sizeof (char ));
445
+ if (allocated ) {
446
+ msr -> stream_input_data = allocated ;
447
+ msr -> stream_input_allocated_length = allocate ;
448
+ }
449
+ else {
450
+ * error_msg = apr_psprintf (
451
+ msr -> mp ,
452
+ "Unable to allocate memory to hold request body on stream. Asked for %" APR_SIZE_T_FMT " bytes." ,
453
+ allocate );
444
454
return -1 ;
445
-
446
- memset (data , 0 , msr -> stream_input_length + 1 - buflen );
447
- memcpy (data , msr -> stream_input_data , msr -> stream_input_length - buflen );
448
-
449
- stream_input_body = (char * )realloc (msr -> stream_input_data , msr -> stream_input_length + 1 );
450
-
451
- msr -> stream_input_data = (char * )stream_input_body ;
452
- }
453
-
454
- if (msr -> stream_input_data == NULL ) {
455
- if (data ) {
456
- free (data );
457
- data = NULL ;
458
455
}
459
- * error_msg = apr_psprintf (msr -> mp , "Unable to allocate memory to hold request body on stream. Asked for %" APR_SIZE_T_FMT " bytes." ,
460
- msr -> stream_input_length + 1 );
461
- return -1 ;
462
456
}
457
+ else {
458
+ // Do we need to expand the space we have previously allocated?
459
+ if ((msr -> stream_input_length + buflen ) > msr -> stream_input_allocated_length ) {
463
460
464
- memset (msr -> stream_input_data , 0 , msr -> stream_input_length + 1 );
461
+ // If this becomes a hotspot again, consider increasing by some percent extra each time, for fewer reallocs
462
+ allocate = msr -> stream_input_length + buflen ;
465
463
466
- if (first_pkt ) {
467
- memcpy (msr -> stream_input_data , buffer , msr -> stream_input_length );
468
- } else {
469
- memcpy (msr -> stream_input_data , data , msr -> stream_input_length - buflen );
470
- memcpy (msr -> stream_input_data + (msr -> stream_input_length - buflen ), buffer , buflen );
464
+ allocated = (char * ) realloc (msr -> stream_input_data , allocate );
465
+ if (allocated ) {
466
+ msr -> stream_input_data = allocated ;
467
+ msr -> stream_input_allocated_length = allocate ;
468
+ }
469
+ else {
470
+ * error_msg = apr_psprintf (
471
+ msr -> mp ,
472
+ "Unable to reallocate memory to hold request body on stream. Asked for %" APR_SIZE_T_FMT " bytes." ,
473
+ allocate );
474
+ free (msr -> stream_input_data );
475
+ return -1 ;
476
+ }
477
+ }
471
478
}
472
479
473
- if (data ) {
474
- free (data );
475
- data = NULL ;
476
- }
480
+ // Append buffer to msr->stream_input_data
481
+ memcpy (msr -> stream_input_data + msr -> stream_input_length , buffer , buflen );
482
+ msr -> stream_input_length += buflen ;
477
483
478
484
return 1 ;
479
485
}
486
+
480
487
/**
481
488
* Replace a bunch of chunks holding a request body with a single large chunk.
482
489
*/
@@ -884,15 +891,15 @@ apr_status_t modsecurity_request_body_clear(modsec_rec *msr, char **error_msg) {
884
891
885
892
if (msr -> msc_reqbody_filename != NULL ) {
886
893
if (keep_body ) {
887
- /* Move request body (which is a file) to the storage area. */
888
- const char * put_filename = NULL ;
889
- const char * put_basename = NULL ;
890
-
891
894
if (strcmp (msr -> txcfg -> upload_dir , msr -> txcfg -> tmp_dir ) == 0 ) {
892
895
msr_log (msr , 4 , "Not moving file to identical location." );
893
896
goto nullify ;
894
897
}
895
898
899
+ /* Move request body (which is a file) to the storage area. */
900
+ const char * put_filename = NULL ;
901
+ const char * put_basename = NULL ;
902
+
896
903
/* Construct the new filename. */
897
904
put_basename = file_basename (msr -> msc_reqbody_mp , msr -> msc_reqbody_filename );
898
905
if (put_basename == NULL ) {
0 commit comments