@@ -146,39 +146,14 @@ pub async fn publish(app: AppState, req: Parts, body: Body) -> AppResult<Json<Go
146146 . check_rate_limit ( auth. user ( ) . id , rate_limit_action, & mut conn)
147147 . await ?;
148148
149- let tarball_len = reader. read_u32_le ( ) . await . map_err ( |e| {
150- if e. kind ( ) == std:: io:: ErrorKind :: UnexpectedEof {
151- bad_request ( "invalid tarball length" )
152- } else {
153- e. into ( )
154- }
155- } ) ?;
156- let content_length = tarball_len as u64 ;
157-
158149 let maximums = Maximums :: new (
159150 existing_crate. as_ref ( ) . and_then ( |c| c. max_upload_size ) ,
160151 app. config . max_upload_size ,
161152 app. config . max_unpack_size ,
162153 ) ;
163154
164- if content_length > maximums. max_upload_size {
165- return Err ( custom (
166- StatusCode :: PAYLOAD_TOO_LARGE ,
167- format ! ( "max upload size is: {}" , maximums. max_upload_size) ,
168- ) ) ;
169- }
170-
171- let mut tarball_bytes = vec ! [ 0 ; tarball_len as usize ] ;
172- reader. read_exact ( & mut tarball_bytes) . await . map_err ( |e| {
173- if e. kind ( ) == std:: io:: ErrorKind :: UnexpectedEof {
174- let message = format ! ( "invalid tarball length for remaining payload: {tarball_len}" ) ;
175- bad_request ( message)
176- } else {
177- e. into ( )
178- }
179- } ) ?;
180-
181- let tarball_bytes = Bytes :: from ( tarball_bytes) ;
155+ let tarball_bytes = read_tarball_bytes ( & mut reader, maximums. max_upload_size as u32 ) . await ?;
156+ let content_length = tarball_bytes. len ( ) as u64 ;
182157
183158 let pkg_name = format ! ( "{}-{}" , & * metadata. name, & version_string) ;
184159 let tarball_info =
@@ -633,6 +608,36 @@ async fn read_json_metadata<R: AsyncRead + Unpin>(
633608 . map_err ( |e| bad_request ( format_args ! ( "invalid upload request: {e}" ) ) )
634609}
635610
611+ async fn read_tarball_bytes < R : AsyncRead + Unpin > (
612+ reader : & mut R ,
613+ max_length : u32 ,
614+ ) -> Result < Bytes , BoxedAppError > {
615+ let tarball_len = reader. read_u32_le ( ) . await . map_err ( |e| {
616+ if e. kind ( ) == std:: io:: ErrorKind :: UnexpectedEof {
617+ bad_request ( "invalid tarball length" )
618+ } else {
619+ e. into ( )
620+ }
621+ } ) ?;
622+
623+ if tarball_len > max_length {
624+ let message = format ! ( "max upload size is: {}" , max_length) ;
625+ return Err ( custom ( StatusCode :: PAYLOAD_TOO_LARGE , message) ) ;
626+ }
627+
628+ let mut tarball_bytes = vec ! [ 0 ; tarball_len as usize ] ;
629+ reader. read_exact ( & mut tarball_bytes) . await . map_err ( |e| {
630+ if e. kind ( ) == std:: io:: ErrorKind :: UnexpectedEof {
631+ let message = format ! ( "invalid tarball length for remaining payload: {tarball_len}" ) ;
632+ bad_request ( message)
633+ } else {
634+ e. into ( )
635+ }
636+ } ) ?;
637+
638+ Ok ( Bytes :: from ( tarball_bytes) )
639+ }
640+
636641async fn is_reserved_name ( name : & str , conn : & mut AsyncPgConnection ) -> QueryResult < bool > {
637642 select ( exists ( reserved_crate_names:: table. filter (
638643 canon_crate_name ( reserved_crate_names:: name) . eq ( canon_crate_name ( name) ) ,
0 commit comments