Skip to content

Instantly share code, notes, and snippets.

@Cyberax
Created February 28, 2020 22:07
Show Gist options
  • Save Cyberax/693f1d1f2c4550478615047e8ca866e0 to your computer and use it in GitHub Desktop.
Save Cyberax/693f1d1f2c4550478615047e8ca866e0 to your computer and use it in GitHub Desktop.
Bug repro
#!/bin/bash
cat >main.go <<REPRO
package main
import (
"bytes"
"fmt"
"time"
)
func parseArray(src, del []byte) (dims []int, elems [][]byte, err error) {
var depth, i int
if len(src) < 1 || src[0] != '{' {
return nil, nil, fmt.Errorf("pq: unable to parse array; expected %q at offset %d", '{', 0)
}
Open:
for i < len(src) {
switch src[i] {
case '{':
depth++
i++
case '}':
elems = make([][]byte, 0)
goto Close
default:
break Open
}
}
dims = make([]int, i)
Element:
for i < len(src) {
switch src[i] {
case '{':
if depth == len(dims) {
break Element
}
depth++
dims[depth-1] = 0
i++
case '"':
var elem = []byte{}
var escape bool
for i++; i < len(src); i++ {
if escape {
elem = append(elem, src[i])
escape = false
} else {
switch src[i] {
default:
elem = append(elem, src[i])
case '\\\\':
escape = true
case '"':
elems = append(elems, elem)
i++
break Element
}
}
}
default:
for start := i; i < len(src); i++ {
if bytes.HasPrefix(src[i:], del) || src[i] == '}' {
elem := src[start:i]
if len(elem) == 0 {
return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i)
}
if bytes.Equal(elem, []byte("NULL")) {
elem = nil
}
elems = append(elems, elem)
break Element
}
}
}
}
for i < len(src) {
if bytes.HasPrefix(src[i:], del) && depth > 0 {
dims[depth-1]++
i += len(del)
goto Element
} else if src[i] == '}' && depth > 0 {
dims[depth-1]++
depth--
i++
} else {
return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i)
}
}
Close:
for i < len(src) {
if src[i] == '}' && depth > 0 {
depth--
i++
} else {
return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i)
}
}
if depth > 0 {
err = fmt.Errorf("pq: unable to parse array; expected %q at offset %d", '}', i)
}
if err == nil {
for _, d := range dims {
if (len(elems) % d) != 0 {
err = fmt.Errorf("pq: multidimensional arrays must have elements with matching dimensions")
}
}
}
return
}
func main() {
arr := []byte("{")
for i := 2; i<35137; i++ {
arr = append(arr, fmt.Sprintf("%d,", i)...)
}
arr[len(arr)-1] = byte('}')
del := []byte{44}
start := time.Now()
parseArray(arr, del)
fmt.Printf("Elapsed %d ms\\n", time.Now().Sub(start).Milliseconds())
}
REPRO
go run main.go
go get github.com/go-delve/delve/cmd/dlv
echo "continue" | go run github.com/go-delve/delve/cmd/dlv debug main.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment