Skip to content

Commit 0639ea1

Browse files
committed
Improve sam_hdr_sanitise()
Remove some variables that are no longer needed. Make it count lines. Ensure adding '\n' doesn't overflow h->l_text. Simplify logic for adding the '\n' a bit.
1 parent 72a7c2a commit 0639ea1

File tree

1 file changed

+38
-19
lines changed

1 file changed

+38
-19
lines changed

sam.c

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)