another fuzzing find

This commit is contained in:
Blake Mizerany 2024-04-04 00:47:52 -07:00
parent acf1cb1dc4
commit d85fbd0e99
6 changed files with 43 additions and 20 deletions

View File

@ -19,6 +19,15 @@ const (
Build Build
) )
var kindNames = map[PartKind]string{
Invalid: "Invalid",
Domain: "Domain",
Namespace: "Namespace",
Name: "Name",
Tag: "Tag",
Build: "Build",
}
// Ref is an opaque reference to a blob. // Ref is an opaque reference to a blob.
// //
// It is comparable and can be used as a map key. // It is comparable and can be used as a map key.
@ -219,12 +228,11 @@ func Parts(s string) iter.Seq2[PartKind, string] {
return return
} }
yieldValid := func(kind PartKind, value string) bool { yieldValid := func(kind PartKind, part string) bool {
if !isValidPart(value) { if !isValidPart(part) {
yield(Invalid, "") return yield(Invalid, "")
return false
} }
return yield(kind, value) return yield(kind, part)
} }
state, j := Build, len(s) state, j := Build, len(s)
@ -238,16 +246,18 @@ func Parts(s string) iter.Seq2[PartKind, string] {
} }
state, j = Tag, i state, j = Tag, i
default: default:
yield(Invalid, "")
return return
} }
case ':': case ':':
switch state { switch state {
case Build, Tag: case Build, Tag:
if yieldValid(Tag, s[i+1:j]) { if !yieldValid(Tag, s[i+1:j]) {
state, j = Tag, i return
} }
state, j = Name, i state, j = Name, i
default: default:
yield(Invalid, "")
return return
} }
case '/': case '/':
@ -262,23 +272,21 @@ func Parts(s string) iter.Seq2[PartKind, string] {
return return
} }
state, j = Domain, i state, j = Domain, i
case Domain: default:
// domain is not allowed to have slashes
yield(Invalid, "") yield(Invalid, "")
return return
}
default: default:
if !isValidPart(s[i : i+1]) {
yield(Invalid, "")
return return
} }
} }
} }
// handle the first part based on final state if state <= Namespace {
switch state { yieldValid(state, s[:j])
case Domain: } else {
yieldValid(Domain, s[:j])
case Namespace:
yieldValid(Namespace, s[:j])
default:
yieldValid(Name, s[:j]) yieldValid(Name, s[:j])
} }
} }

View File

@ -21,12 +21,19 @@ var testRefs = map[string]Ref{
"mistral:7b+q4_0": {name: "mistral", tag: "7b", build: "Q4_0"}, "mistral:7b+q4_0": {name: "mistral", tag: "7b", build: "Q4_0"},
"llama2": {name: "llama2"}, "llama2": {name: "llama2"},
// invalid // invalid (includes fuzzing trophies)
"mistral:7b+Q4_0:latest": {}, "mistral:7b+Q4_0:latest": {},
"mi tral": {}, "mi tral": {},
"x/y/z/foo": {}, "x/y/z/foo": {},
"/0": {}, "/0": {},
"0 /0": {},
"0 /": {},
"0/": {}, "0/": {},
":": {},
":/0": {},
"+0/00000": {},
"0+.\xf2\x80\xf6\x9d00000\xe5\x99\xe6\xd900\xd90\xa60\x91\xdc0\xff\xbf\x99\xe800\xb9\xdc\xd6\xc300\x970\xfb\xfd0\xe0\x8a\xe1\xad\xd40\x9700\xa80\x980\xdd0000\xb00\x91000\xfe0\x89\x9b\x90\x93\x9f0\xe60\xf7\x84\xb0\x87\xa5\xff0\xa000\x9a\x85\xf6\x85\xfe\xa9\xf9\xe9\xde00\xf4\xe0\x8f\x81\xad\xde00\xd700\xaa\xe000000\xb1\xee0\x91": {},
"0//0": {},
} }
func TestRefParts(t *testing.T) { func TestRefParts(t *testing.T) {
@ -47,7 +54,7 @@ func TestParseRef(t *testing.T) {
// test round-trip // test round-trip
if ParseRef(got.String()) != got { if ParseRef(got.String()) != got {
t.Errorf("String() = %q; want %q", got.String(), s) t.Errorf("String() = %s; want %s", got.String(), s)
} }
}) })
} }
@ -125,7 +132,7 @@ func FuzzParseRef(f *testing.F) {
r1 := ParseRef(r0.String()) r1 := ParseRef(r0.String())
if r0 != r1 { if r0 != r1 {
t.Errorf("round-trip mismatch: %q != %q", r0, r1) t.Errorf("round-trip mismatch: %+v != %+v", r0, r1)
} }
}) })
} }

View File

@ -0,0 +1,2 @@
go test fuzz v1
string("0//0")

View File

@ -0,0 +1,2 @@
go test fuzz v1
string("+0/00000")

View File

@ -0,0 +1,2 @@
go test fuzz v1
string(":")

View File

@ -0,0 +1,2 @@
go test fuzz v1
string("0+.\xf2\x80\xf6\x9d00000\xe5\x99\xe6\xd900\xd90\xa60\x91\xdc0\xff\xbf\x99\xe800\xb9\xdc\xd6\xc300\x970\xfb\xfd0\xe0\x8a\xe1\xad\xd40\x9700\xa80\x980\xdd0000\xb00\x91000\xfe0\x89\x9b\x90\x93\x9f0\xe60\xf7\x84\xb0\x87\xa5\xff0\xa000\x9a\x85\xf6\x85\xfe\xa9\xf9\xe9\xde00\xf4\xe0\x8f\x81\xad\xde00\xd700\xaa\xe000000\xb1\xee0\x91")