Skip to content

Commit aae5a62

Browse files
ankanesonnemusk
andcommitted
Fixed panics with Parse methods - resolves #29
Co-authored-by: sonnemusk <sonnemusk@gmail.com>
1 parent 62a8ec1 commit aae5a62

7 files changed

Lines changed: 86 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.4.1 (unreleased)
2+
3+
- Fixed panics with `Parse` methods
4+
15
## 0.4.0 (2026-05-18)
26

37
- Changed `ent` and `pgx` packages to modules

‎halfvec.go‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ func (v HalfVector) String() string {
3535

3636
// Parse parses a string representation of a half vector.
3737
func (v *HalfVector) Parse(s string) error {
38+
if len(s) < 2 {
39+
return fmt.Errorf("malformed halfvec literal")
40+
}
41+
42+
if len(s) == 2 {
43+
v.vec = []float32{}
44+
return nil
45+
}
46+
3847
sp := strings.Split(s[1:len(s)-1], ",")
3948
v.vec = make([]float32, 0, len(sp))
4049
for i := 0; i < len(sp); i++ {

‎sparsevec.go‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,33 @@ func (v SparseVector) String() string {
9595
// Parse parses a string representation of a sparse vector.
9696
func (v *SparseVector) Parse(s string) error {
9797
sp := strings.SplitN(s, "/", 2)
98+
if len(sp) != 2 {
99+
return fmt.Errorf("malformed sparsevec literal")
100+
}
98101

99102
dim, err := strconv.ParseInt(sp[1], 10, 32)
100103
if err != nil {
101104
return err
102105
}
103106

104-
elements := strings.Split(sp[0][1:len(sp[0])-1], ",")
107+
if len(sp[0]) < 2 {
108+
return fmt.Errorf("malformed sparsevec literal")
109+
}
110+
111+
elements := []string{}
112+
if len(sp[0]) > 2 {
113+
elements = strings.Split(sp[0][1:len(sp[0])-1], ",")
114+
}
115+
105116
v.dim = int32(dim)
106117
v.indices = make([]int32, 0, len(elements))
107118
v.values = make([]float32, 0, len(elements))
108119

109120
for i := 0; i < len(elements); i++ {
110121
ep := strings.SplitN(elements[i], ":", 2)
122+
if len(ep) != 2 {
123+
return fmt.Errorf("malformed sparsevec literal")
124+
}
111125

112126
n, err := strconv.ParseInt(ep[0], 10, 32)
113127
if err != nil {

‎test/halfvec_test.go‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ func TestHalfVectorParse(t *testing.T) {
3232
if !reflect.DeepEqual(vec.Slice(), []float32{1, 2, 3}) {
3333
t.Error()
3434
}
35+
36+
err = vec.Parse("[]")
37+
if err != nil {
38+
panic(err)
39+
}
40+
if !reflect.DeepEqual(vec.Slice(), []float32{}) {
41+
t.Error()
42+
}
43+
44+
err = vec.Parse("")
45+
if err == nil || err.Error() != "malformed halfvec literal" {
46+
t.Error()
47+
}
3548
}
3649

3750
func TestHalfVectorMarshal(t *testing.T) {

‎test/sparsevec_test.go‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,27 @@ func TestSparseVectorParse(t *testing.T) {
7373
if !reflect.DeepEqual(vec.Slice(), []float32{1, 0, 2, 0, 3, 0}) {
7474
t.Error()
7575
}
76+
77+
err = vec.Parse("{}/0")
78+
if err != nil {
79+
panic(err)
80+
}
81+
if !reflect.DeepEqual(vec.Slice(), []float32{}) {
82+
t.Error()
83+
}
84+
85+
err = vec.Parse("")
86+
if err == nil || err.Error() != "malformed sparsevec literal" {
87+
t.Error()
88+
}
89+
90+
err = vec.Parse("/6")
91+
if err == nil || err.Error() != "malformed sparsevec literal" {
92+
t.Error()
93+
}
94+
95+
err = vec.Parse("{1}/6")
96+
if err == nil || err.Error() != "malformed sparsevec literal" {
97+
t.Error()
98+
}
7699
}

‎test/vector_test.go‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ func TestVectorParse(t *testing.T) {
3232
if !reflect.DeepEqual(vec.Slice(), []float32{1, 2, 3}) {
3333
t.Error()
3434
}
35+
36+
err = vec.Parse("[]")
37+
if err != nil {
38+
panic(err)
39+
}
40+
if !reflect.DeepEqual(vec.Slice(), []float32{}) {
41+
t.Error()
42+
}
43+
44+
err = vec.Parse("")
45+
if err == nil || err.Error() != "malformed vector literal" {
46+
t.Error()
47+
}
3548
}
3649

3750
func TestVectorMarshal(t *testing.T) {

‎vector.go‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ func (v Vector) String() string {
4545

4646
// Parse parses a string representation of a vector.
4747
func (v *Vector) Parse(s string) error {
48+
if len(s) < 2 {
49+
return fmt.Errorf("malformed vector literal")
50+
}
51+
52+
if len(s) == 2 {
53+
v.vec = []float32{}
54+
return nil
55+
}
56+
4857
sp := strings.Split(s[1:len(s)-1], ",")
4958
v.vec = make([]float32, 0, len(sp))
5059
for i := 0; i < len(sp); i++ {

0 commit comments

Comments
 (0)