@@ -428,55 +428,62 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
428428}
429429
430430apr_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 ;
434433
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+ }
442443
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 );
444454return -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 ;
458455 }
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 ;
462456 }
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 ) {
463460
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 ;
465463
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+ }
471478 }
472479
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 ;
477483
478484return 1 ;
479485}
486+
480487/**
481488 * Replace a bunch of chunks holding a request body with a single large chunk.
482489 */
@@ -884,15 +891,15 @@ apr_status_t modsecurity_request_body_clear(modsec_rec *msr, char **error_msg) {
884891
885892if (msr -> msc_reqbody_filename != NULL ) {
886893if (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-
891894if (strcmp (msr -> txcfg -> upload_dir ,msr -> txcfg -> tmp_dir )== 0 ) {
892895msr_log (msr ,4 ,"Not moving file to identical location." );
893896 gotonullify ;
894897 }
895898
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+
896903/* Construct the new filename. */
897904put_basename = file_basename (msr -> msc_reqbody_mp ,msr -> msc_reqbody_filename );
898905if (put_basename == NULL ) {