Skip to content

Commit 72422ef

Browse files
authored
Switch from strtol to hts_str2uint in mod parsing (#1957)
Switch from strtol to hts_str2uint in mod parsing
1 parent f4165e9 commit 72422ef

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

sam_mods.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ int bam_parse_basemod2(const bam1_t *b, hts_base_mod_state *state,
272272
char *cp = (char *)mm+1;
273273
int mod_num = 0;
274274
int implicit = 1;
275+
int failed = 0;
275276
while (*cp) {
276277
for (; *cp; cp++) {
277278
// cp should be [ACGTNU][+-]([a-zA-Z]+|[0-9]+)[.?]?(,\d+)*;
@@ -295,7 +296,12 @@ int bam_parse_basemod2(const bam1_t *b, hts_base_mod_state *state,
295296
char *cp_end = NULL;
296297
int chebi = 0;
297298
if (isdigit_c(*cp)) {
298-
chebi = strtol(cp, &cp_end, 10);
299+
chebi = (int)hts_str2uint(cp, &cp_end, 31, &failed);
300+
if (cp_end == cp || failed) {
301+
hts_log_error("%s: malformed MM tag (invalid ChEBI code)",
302+
bam_get_qname(b));
303+
return -1;
304+
}
299305
cp = cp_end;
300306
ms = cp-1;
301307
} else {
@@ -341,8 +347,8 @@ int bam_parse_basemod2(const bam1_t *b, hts_base_mod_state *state,
341347
if (*cp == 0 || *cp == ';')
342348
break;
343349

344-
delta = strtol(cp, &cp_end, 10);
345-
if (cp_end == cp) {
350+
delta = (long)hts_str2uint(cp, &cp_end, 31, &failed);
351+
if (cp_end == cp || failed) {
346352
hts_log_error("%s: Hit end of MM tag. Missing "
347353
"semicolon?", bam_get_qname(b));
348354
return -1;
@@ -354,11 +360,14 @@ int bam_parse_basemod2(const bam1_t *b, hts_base_mod_state *state,
354360
}
355361
delta = freq[seqi_rc[btype]] - total_seq; // remainder
356362
} else {
357-
delta = *cp == ','
358-
? strtol(cp+1, &cp_end, 10)
359-
: 0;
360-
if (!cp_end) {
361-
// empty list
363+
if (*cp == ',') {
364+
delta = (long)hts_str2uint(cp+1, &cp_end, 31, &failed);
365+
if (cp_end == cp+1 || failed) {
366+
hts_log_error("%s: Failed to parse integer from MM tag",
367+
bam_get_qname(b));
368+
return -1;
369+
}
370+
} else {
362371
delta = INT_MAX;
363372
cp_end = cp;
364373
}
@@ -494,9 +503,11 @@ int bam_mods_at_next_pos(const bam1_t *b, hts_base_mod_state *state,
494503
? -state->MLstride[i]
495504
: +state->MLstride[i];
496505

506+
int failed = 0;
497507
if (b->core.flag & BAM_FREVERSE) {
498508
// process MM list backwards
499509
char *cp;
510+
char *tmp;
500511

501512
if (state->MMend[i]-1 < state->MM[i]) {
502513
// Should be impossible to hit if coding is correct
@@ -508,15 +519,19 @@ int bam_mods_at_next_pos(const bam1_t *b, hts_base_mod_state *state,
508519
break;
509520
state->MMend[i] = cp;
510521
if (cp != state->MM[i])
511-
state->MMcount[i] = strtol(cp+1, NULL, 10);
522+
state->MMcount[i] = (int)hts_str2uint(cp + 1, &tmp, 31, &failed);
512523
else
513524
state->MMcount[i] = INT_MAX;
514525
} else {
515526
if (*state->MM[i] == ',')
516-
state->MMcount[i] = strtol(state->MM[i]+1, &state->MM[i], 10);
527+
state->MMcount[i] = (int)hts_str2uint(state->MM[i] + 1, &state->MM[i], 31, &failed);
517528
else
518529
state->MMcount[i] = INT_MAX;
519530
}
531+
if (failed) {
532+
hts_log_error("%s: Error parsing unsigned integer from MM tag", bam_get_qname(b));
533+
return -1;
534+
}
520535

521536
// Multiple mods at the same coords.
522537
for (j=i+1; j < state->nmods && state->MM[j] == MMptr; j++) {

0 commit comments

Comments
 (0)