Skip to content

Commit 47ea441

Browse files
sirus20x6pd3
authored andcommitted
Replace assert() with proper error handling for user-triggerable conditions
assert() is compiled out in release builds (NDEBUG), causing silent undefined behavior or buffer overflows when triggered by malformed input. - consensus.c: Replace asserts on variant overlap trimming, unreachable overlap case, and fasta buffer bounds with error() calls - convert.c: Replace GT type asserts with warning+skip; add allele index bounds checks in process_tgt and process_iupac_gt - vcfconcat.c: Replace bgzf block size assert with error() call - filter.c: Add NULL check for getenv("HOME") and getenv("HOMEDRIVE")/ getenv("HOMEPATH") in expand_path()
1 parent a49df0c commit 47ea441

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

consensus.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,9 @@ static void apply_variant(args_t *args, bcf1_t *rec)
815815
// forward
816816
int ntrim = args->fa_frz_pos - rec->pos + 1;
817817
int nref = strlen(rec->d.allele[0]);
818-
assert( ntrim < nref );
818+
if ( ntrim >= nref )
819+
error("Error: failed to trim overlapping variant at %s:%"PRId64", ntrim=%d >= nref=%d. Is the VCF normalized?\n",
820+
bcf_seqname(args->hdr,rec),(int64_t)rec->pos+1,ntrim,nref);
819821
rec->pos += ntrim;
820822
rec->rlen -= ntrim;
821823
memmove(rec->d.allele[0],rec->d.allele[0]+ntrim,nref-ntrim);
@@ -853,7 +855,6 @@ static void apply_variant(args_t *args, bcf1_t *rec)
853855
}
854856
else if ( strlen(ref_allele) < -idx ) // the ref allele is shorter but overlaps the fa sequence? This should never happen
855857
{
856-
assert(0);
857858
fprintf(stderr,"Warning: ignoring overlapping variant starting at %s:%"PRId64"\n", bcf_seqname(args->hdr,rec),(int64_t) rec->pos+1);
858859
return;
859860
}
@@ -1002,7 +1003,9 @@ static void apply_variant(args_t *args, bcf1_t *rec)
10021003
if ( len_diff <= 0 )
10031004
{
10041005
// deletion or same size event
1005-
assert( args->fa_buf.l >= idx+rec->rlen );
1006+
if ( args->fa_buf.l < idx+rec->rlen )
1007+
error("Error: fasta buffer too short at %s:%"PRId64" (buf length %zu, need %"PRId64"). Is the reference fasta correct?\n",
1008+
bcf_seqname(args->hdr,rec),(int64_t)rec->pos+1,(size_t)args->fa_buf.l,(int64_t)(idx+rec->rlen));
10061009
args->prev_base = args->fa_buf.s[idx+rec->rlen-1];
10071010
args->prev_base_pos = rec->pos + rec->rlen - 1;
10081011
args->prev_is_insert = 0;

convert.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,12 @@ static void process_tgt(convert_t *convert, bcf1_t *line, fmt_t *fmt, int isampl
446446
return;
447447
}
448448

449-
assert( fmt->fmt->type==BCF_BT_INT8 );
449+
if ( fmt->fmt->type!=BCF_BT_INT8 )
450+
{
451+
fprintf(stderr,"Warning: skipping GT field with unexpected type %d at %s:%"PRId64"\n", fmt->fmt->type,bcf_seqname(convert->header,line),(int64_t)line->pos+1);
452+
kputc('.', str);
453+
return;
454+
}
450455

451456
int l;
452457
int8_t *x = (int8_t*)(fmt->fmt->p + isample*fmt->fmt->size); // FIXME: does not work with n_alt >= 64
@@ -456,6 +461,12 @@ static void process_tgt(convert_t *convert, bcf1_t *line, fmt_t *fmt, int isampl
456461
if (x[l]>>1)
457462
{
458463
int ial = (x[l]>>1) - 1;
464+
if ( ial >= line->n_allele )
465+
{
466+
fprintf(stderr,"Warning: allele index %d >= n_allele %d at %s:%"PRId64"\n", ial,line->n_allele,bcf_seqname(convert->header,line),(int64_t)line->pos+1);
467+
kputc('.', str);
468+
continue;
469+
}
459470
kputs(line->d.allele[ial], str);
460471
}
461472
else
@@ -608,7 +619,12 @@ static void process_iupac_gt(convert_t *convert, bcf1_t *line, fmt_t *fmt, int i
608619
return;
609620
}
610621

611-
assert( fmt->fmt->type==BCF_BT_INT8 );
622+
if ( fmt->fmt->type!=BCF_BT_INT8 )
623+
{
624+
fprintf(stderr,"Warning: skipping GT field with unexpected type %d at %s:%"PRId64"\n", fmt->fmt->type,bcf_seqname(convert->header,line),(int64_t)line->pos+1);
625+
kputc('.', str);
626+
return;
627+
}
612628

613629
static const char iupac[4][4] = { {'A','M','R','W'},{'M','C','S','Y'},{'R','S','G','K'},{'W','Y','K','T'} };
614630
int8_t *dat = (int8_t*)convert->dat;
@@ -633,6 +649,12 @@ static void process_iupac_gt(convert_t *convert, bcf1_t *line, fmt_t *fmt, int i
633649
if (x[l]>>1)
634650
{
635651
int ial = (x[l]>>1) - 1;
652+
if ( ial >= line->n_allele )
653+
{
654+
fprintf(stderr,"Warning: allele index %d >= n_allele %d at %s:%"PRId64"\n", ial,line->n_allele,bcf_seqname(convert->header,line),(int64_t)line->pos+1);
655+
kputc('.', str);
656+
continue;
657+
}
636658
kputs(line->d.allele[ial], str);
637659
}
638660
else

filter.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,14 @@ char *expand_path(char *path)
389389
if ( !path[1] || path[1] == '/' )
390390
{
391391
#ifdef _WIN32
392-
kputs(getenv("HOMEDRIVE"), &str);
393-
kputs(getenv("HOMEPATH"), &str);
392+
char *homedrive = getenv("HOMEDRIVE");
393+
char *homepath = getenv("HOMEPATH");
394+
if (homedrive) kputs(homedrive, &str);
395+
if (homepath) kputs(homepath, &str);
394396
#else
395397
// ~ or ~/path
396-
kputs(getenv("HOME"), &str);
398+
char *home = getenv("HOME");
399+
if (home) kputs(home, &str); else kputc('.', &str);
397400
if ( path[1] ) kputs(path+1, &str);
398401
#endif
399402
}

vcfconcat.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,9 @@ static void naive_concat(args_t *args)
939939
if ( !nread ) break;
940940
if ( nread != nheader || check_header(buf)!=0 ) error("\nCould not parse the header of a bgzf block: %s\n",args->fnames[i]);
941941
nblock = unpackInt16(buf+16) + 1;
942-
assert( nblock <= page_size && nblock >= nheader );
942+
if ( nblock > page_size || nblock < nheader )
943+
error("\nError: malformed bgzf block in %s: block size %"PRId64" out of valid range [%d,%d]\n",
944+
args->fnames[i],(int64_t)nblock,nheader,(int)page_size);
943945
nread += bgzf_raw_read(fp, buf+nheader, nblock - nheader);
944946
if ( nread!=nblock ) error("\nCould not read %"PRId64" bytes: %s\n",(uint64_t)nblock,args->fnames[i]);
945947
if ( nread==neof && !memcmp(buf,eof,neof) ) continue;

0 commit comments

Comments
 (0)