Repository: brentp/cyvcf2 (language: python)

Issue:
Accessing Variant num_called property causes segmentation fault
First of all, thanks for the speedy package, @brentp. Much appreciated!

Now, about the issue: whenever I access the `num_called` property of a `Variant` instance, Python crashes with a segmentation fault. The VCF file was generated by the Strelka SNV and indel caller. I'm not familiar with Cython, so I can't readily submit a pull request. I figured this might be an easy fix. Then again, don't we all start by thinking that... 
### Steps to reproduce error

Here's a one-variant [test VCF file](https://github.com/brentp/cyvcf2/files/397933/test.txt). I had to change the file extension to `.txt` to upload it to GitHub. 

I'm using cyvcf2 v0.5.1 on Python v3.5.2. 

```
>>> from cyvcf2 import VCF
>>> vcf = VCF('test.txt')
>>> var = next(vcf)
>>> var.num_called
[1]    43035 segmentation fault  python
```

Let me know if you need anything else! 

Accessing Variant num_called property causes segmentation fault
First of all, thanks for the speedy package, @brentp. Much appreciated!

Now, about the issue: whenever I access the `num_called` property of a `Variant` instance, Python crashes with a segmentation fault. The VCF file was generated by the Strelka SNV and indel caller. I'm not familiar with Cython, so I can't readily submit a pull request. I figured this might be an easy fix. Then again, don't we all start by thinking that... 
### Steps to reproduce error

Here's a one-variant [test VCF file](https://github.com/brentp/cyvcf2/files/397933/test.txt). I had to change the file extension to `.txt` to upload it to GitHub. 

I'm using cyvcf2 v0.5.1 on Python v3.5.2. 

```
>>> from cyvcf2 import VCF
>>> vcf = VCF('test.txt')
>>> var = next(vcf)
>>> var.num_called
[1]    43035 segmentation fault  python
```

Let me know if you need anything else! 



Discussion / hints:
while it shouldn't segfault, you don't have genotypes in your VCF, so `num_called` will never return something sensible. I'll add a guard for this scenario, but at best, it will return None.

Hi just to note this still occurs with version '0.30.18' (latest PyPi release)

Pisces 5.2.11.63 VCFs (From Illumina TSO500) define GT in the header but it's not in the FORMAT field for CNV records 

The VCF 4.3 specification says "The first key must always be the genotype (GT) if it is present. There are no required keys. "

vcf-validator and bcftools say the Pisces VCF is ok
while it shouldn't segfault, you don't have genotypes in your VCF, so `num_called` will never return something sensible. I'll add a guard for this scenario, but at best, it will return None.

Hi just to note this still occurs with version '0.30.18' (latest PyPi release)

Pisces 5.2.11.63 VCFs (From Illumina TSO500) define GT in the header but it's not in the FORMAT field for CNV records 

The VCF 4.3 specification says "The first key must always be the genotype (GT) if it is present. There are no required keys. "

vcf-validator and bcftools say the Pisces VCF is ok

Fix patch:
diff --git a/cyvcf2/cyvcf2.pyx b/cyvcf2/cyvcf2.pyx
index e9239e0..c9da11c 100644
--- a/cyvcf2/cyvcf2.pyx
+++ b/cyvcf2/cyvcf2.pyx
@@ -1494,6 +1494,8 @@ cdef class Variant(object):
             if self._gt_types == NULL:
                 self._gt_phased = <int *>stdlib.malloc(sizeof(int) * self.vcf.n_samples)
                 ngts = bcf_get_genotypes(self.vcf.hdr, self.b, &self._gt_types, &ndst)
+                if ngts < 0:
+                    raise Exception("error parsing genotypes; they may be absent from this record")
                 nper = int(ngts / self.vcf.n_samples)
                 self._ploidy = nper
                 self._gt_idxs = <int *>stdlib.malloc(sizeof(int) * self.vcf.n_samples * nper)


Test patch:
diff --git a/cyvcf2/tests/test-no-genotypes.vcf b/cyvcf2/tests/test-no-genotypes.vcf
new file mode 100644
index 0000000..7901ea9
--- /dev/null
+++ b/cyvcf2/tests/test-no-genotypes.vcf
@@ -0,0 +1,6 @@
+##fileformat=VCFv4.1
+##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
+##FORMAT=<ID=PL,Number=G,Type=Integer,Description="Normalized, Phred-scaled likelihoods for genotypes as defined in the VCF specification">
+##contig=<ID=1,length=249250621,assembly=b37>
+#CHROM	POS	ID	REF	ALT	QUAL	FILTER	INFO	FORMAT	samplea	sampleb
+1	8466747	.	A	T	.	PASS	.	PL	.	36,0
diff --git a/cyvcf2/tests/test_reader.py b/cyvcf2/tests/test_reader.py
index 8d41af7..13f3f9e 100644
--- a/cyvcf2/tests/test_reader.py
+++ b/cyvcf2/tests/test_reader.py
@@ -1316,3 +1316,10 @@ def test_issue236():
 
         assert res[0] == res[1]
         assert len(res[0]) > 0
+
+
+def test_issue17_no_gt():
+    vcf = VCF(os.path.join(HERE, "test-no-genotypes.vcf"))
+    with pytest.raises(Exception):
+        for v in vcf:
+            v.num_called  # Used to give segmentation fault