@@ -759,31 +759,33 @@ static bool s_s3_auto_ranged_put_update(
759759}
760760
761761/**
762- * Helper to compute request body size.
763- * Basically returns either part size or if content is not equally divisible into parts, the size of the remaining last
764- * part.
762+ * Helper to initialize the request ranges and content-length
763+ * based on the request->part_number and meta_request->part_size
765764 */
766- static size_t s_compute_request_body_size (
767- const struct aws_s3_meta_request * meta_request ,
768- uint32_t part_number ,
769- uint64_t * offset_out ) {
770- AWS_PRECONDITION (meta_request );
765+ static int s_compute_request_body_size (const struct aws_s3_meta_request * meta_request , struct aws_s3_request * request ) {
766+ AWS_ERROR_PRECONDITION (meta_request );
767+ AWS_ERROR_PRECONDITION (request );
771768
772769 const struct aws_s3_auto_ranged_put * auto_ranged_put = meta_request -> impl ;
773770
774771 size_t request_body_size = meta_request -> part_size ;
775772 /* Last part--adjust size to match remaining content length. */
776- if (auto_ranged_put -> has_content_length && part_number == auto_ranged_put -> total_num_parts_from_content_length ) {
773+ if (auto_ranged_put -> has_content_length &&
774+ request -> part_number == auto_ranged_put -> total_num_parts_from_content_length ) {
777775 size_t content_remainder = (size_t )(auto_ranged_put -> content_length % (uint64_t )meta_request -> part_size );
778776
779777 if (content_remainder > 0 ) {
780778 request_body_size = content_remainder ;
781779 }
782780 }
783- /* The part_number starts at 1 */
784- * offset_out = (part_number - 1 ) * meta_request -> part_size ;
785-
786- return request_body_size ;
781+ if (aws_mul_u64_checked (request -> part_number - 1 , meta_request -> part_size , & request -> part_range_start )) {
782+ return AWS_OP_ERR ;
783+ }
784+ if (aws_add_u64_checked (request -> part_range_start , request_body_size - 1 , & request -> part_range_end )) {
785+ return AWS_OP_ERR ;
786+ }
787+ request -> content_length = request_body_size ;
788+ return AWS_OP_SUCCESS ;
787789}
788790
789791static int s_verify_part_matches_checksum (
@@ -1085,23 +1087,24 @@ struct aws_future_http_message *s_s3_prepare_upload_part(struct aws_s3_request *
10851087 part_prep -> allocator = allocator ;
10861088 part_prep -> request = request ;
10871089 part_prep -> on_complete = aws_future_http_message_acquire (message_future );
1090+ if (s_compute_request_body_size (meta_request , request )) {
1091+ s_s3_prepare_upload_part_finish (part_prep , aws_last_error_or_unknown ());
1092+ return message_future ;
1093+ }
10881094
10891095 if (request -> fio_streaming ) {
10901096 /* Create the request body stream for the HTTP to read directly from the file. If retry happens, just recreate
10911097 * it. */
10921098 aws_input_stream_release (request -> request_body_stream );
1093- uint64_t offset = 0 ;
1094- size_t request_body_size = s_compute_request_body_size (meta_request , request -> part_number , & offset );
10951099 AWS_ASSERT (meta_request -> request_body_parallel_stream != NULL );
1100+ int error_code = AWS_ERROR_SUCCESS ;
10961101 request -> request_body_stream = aws_part_streaming_input_stream_new (
10971102 allocator ,
10981103 meta_request -> request_body_parallel_stream ,
10991104 request -> ticket ,
1100- offset ,
1101- request_body_size ,
1105+ request -> part_range_start ,
1106+ ( size_t ) request -> content_length ,
11021107 meta_request -> fio_opts .direct_io );
1103- request -> content_length = request_body_size ;
1104- int error_code = AWS_ERROR_SUCCESS ;
11051108
11061109 if (request -> num_times_prepared == 0 ) {
11071110 if (s_s3_new_upload_part_info_after_body (request , meta_request , false)) {
@@ -1117,15 +1120,14 @@ struct aws_future_http_message *s_s3_prepare_upload_part(struct aws_s3_request *
11171120 * from an upload that had been paused) */
11181121
11191122 /* Read the body */
1120- uint64_t offset = 0 ;
1121- size_t request_body_size = s_compute_request_body_size (meta_request , request -> part_number , & offset );
11221123 if (request -> request_body .capacity == 0 ) {
11231124 AWS_FATAL_ASSERT (request -> ticket );
11241125 request -> request_body = aws_s3_buffer_ticket_claim (request -> ticket );
1125- request -> request_body .capacity = request_body_size ;
1126+ request -> request_body .capacity = ( size_t ) request -> content_length ;
11261127 }
11271128
1128- part_prep -> asyncstep_read_part = aws_s3_meta_request_read_body (meta_request , offset , & request -> request_body );
1129+ part_prep -> asyncstep_read_part =
1130+ aws_s3_meta_request_read_body (meta_request , request -> part_range_start , & request -> request_body );
11291131 aws_future_bool_register_callback (
11301132 part_prep -> asyncstep_read_part , s_s3_prepare_upload_part_on_read_done , part_prep );
11311133 } else {
@@ -1159,21 +1161,21 @@ static void s_s3_prepare_upload_part_on_read_done(void *user_data) {
11591161 request -> request_body .capacity );
11601162 goto on_done ;
11611163 }
1162- /* Reading succeeded. */
1163- request -> content_length = request -> request_body .len ;
11641164 bool is_body_stream_at_end = aws_future_bool_get_result (part_prep -> asyncstep_read_part );
1165-
1166- uint64_t offset = 0 ;
1167- size_t request_body_size = s_compute_request_body_size (meta_request , request -> part_number , & offset );
11681165 /* If Content-Length is defined, check that we read the expected amount */
1169- if (has_content_length && (request -> request_body .len < request_body_size )) {
1166+ if (has_content_length && (request -> request_body .len < request -> content_length )) {
11701167 error_code = AWS_ERROR_S3_INCORRECT_CONTENT_LENGTH ;
11711168 AWS_LOGF_ERROR (
11721169 AWS_LS_S3_META_REQUEST ,
11731170 "id=%p: Request body is smaller than 'Content-Length' header said it would be" ,
11741171 (void * )meta_request );
11751172 goto on_done ;
11761173 }
1174+ if (!has_content_length && (request -> request_body .len < request -> content_length )) {
1175+ /* The stream is not ready to provide enough data as expected. Update the tracking numbers. */
1176+ request -> content_length = request -> request_body .len ;
1177+ request -> part_range_end = request -> part_range_start + request -> content_length - 1 ;
1178+ }
11771179 request -> is_noop = request -> part_number >
11781180 1 && /* allow first part to have 0 length to support empty unknown content length objects. */
11791181 request -> request_body .len == 0 ;
0 commit comments