@@ -754,47 +754,66 @@ static bam_hdr_t *sam_hdr_sanitise(bam_hdr_t *h) {
754754 if (h -> l_text == 0 )
755755 return h ;
756756
757- uint32_t i , j ;
758- char * cp = h -> text , last = 0 ;
759- for (i = j = 0 ; i < h -> l_text ; i ++ ) {
757+ uint32_t i , lnum = 0 ;
758+ char * cp = h -> text , last = '\n' ;
759+ for (i = 0 ; i < h -> l_text ; i ++ ) {
760760 // NB: l_text excludes terminating nul. This finds early ones.
761761 if (cp [i ] == 0 )
762762 break ;
763763
764764 // Error on \n[^@], including duplicate newlines
765765 if (last == '\n' ) {
766+ lnum ++ ;
766767 if (cp [i ] != '@' ) {
767768 if (hts_verbose >= 1 )
768- fprintf (stderr , "[E::%s] Malformed SAM header.\n" , __func__ );
769+ fprintf (stderr ,
770+ "[E::%s] Malformed SAM header at line %u.\n" ,
771+ __func__ , lnum );
769772 bam_hdr_destroy (h );
770773 return NULL ;
771774 }
772775 }
773776
774- last = cp [j ++ ] = cp [ i ];
777+ last = cp [i ];
775778 }
776779
777- // Add trailing newline and/or trailing nul if required.
778- if (j + (last != '\n' ) + (i < h -> l_text ) > h -> l_text ) {
779- char * np = realloc (cp , h -> l_text + 2 );
780- if (!np ) {
781- bam_hdr_destroy (h );
782- return NULL ;
783- }
784- h -> text = cp = np ;
780+ if (i < h -> l_text ) { // Early nul found. Complain if not just padding.
781+ uint32_t j = i ;
782+ while (j < h -> l_text && cp [j ] == '\0' ) j ++ ;
783+ if (j < h -> l_text && hts_verbose >= 2 )
784+ fprintf (stderr , "[W::%s] Unexpected NUL character in header. "
785+ "Possibly truncated.\n" , __func__ );
785786 }
786787
788+ // Add trailing newline and/or trailing nul if required.
787789 if (last != '\n' ) {
788790 if (hts_verbose >= 2 )
789791 fprintf (stderr , "[W::%s] Missing trailing newline on SAM header. "
790792 "Possibly truncated.\n" , __func__ );
791- cp [j ++ ] = '\n' ;
792- }
793793
794- // l_text may be larger already due to multiple nul padding
795- if (h -> l_text < j )
796- h -> l_text = j ;
797- cp [h -> l_text ] = '\0' ;
794+ if (h -> l_text == UINT32_MAX ) {
795+ if (hts_verbose >= 1 )
796+ fprintf (stderr , "[E::%s] No room for extra newline.\n" ,
797+ __func__ );
798+ bam_hdr_destroy (h );
799+ return NULL ;
800+ }
801+
802+ if (i >= h -> l_text - 1 ) {
803+ cp = realloc (h -> text , (size_t ) h -> l_text + 2 );
804+ if (!cp ) {
805+ bam_hdr_destroy (h );
806+ return NULL ;
807+ }
808+ h -> text = cp ;
809+ }
810+ cp [i ++ ] = '\n' ;
811+
812+ // l_text may be larger already due to multiple nul padding
813+ if (h -> l_text < i )
814+ h -> l_text = i ;
815+ cp [h -> l_text ] = '\0' ;
816+ }
798817
799818 return h ;
800819}
0 commit comments