Created
February 28, 2020 22:07
-
-
Save Cyberax/693f1d1f2c4550478615047e8ca866e0 to your computer and use it in GitHub Desktop.
Bug repro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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