Skip to content

Commit

Permalink
Merge pull request #1879 from giuseppe/fix-chunked-name-escaping
Browse files Browse the repository at this point in the history
chunked: fix unmarshaling of file names
  • Loading branch information
openshift-merge-bot[bot] authored Apr 9, 2024
2 parents 58bffca + f388a77 commit a3d902f
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 53 deletions.
58 changes: 10 additions & 48 deletions pkg/chunked/cache_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -652,45 +652,9 @@ func (c *layersCache) findChunkInOtherLayers(chunk *internal.FileMetadata) (stri
}

func unmarshalToc(manifest []byte) (*internal.TOC, error) {
var buf bytes.Buffer
count := 0
var toc internal.TOC

iter := jsoniter.ParseBytes(jsoniter.ConfigFastest, manifest)
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
if strings.ToLower(field) != "entries" {
iter.Skip()
continue
}
for iter.ReadArray() {
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
switch strings.ToLower(field) {
case "type", "name", "linkname", "digest", "chunkdigest", "chunktype", "modtime", "accesstime", "changetime":
count += len(iter.ReadStringAsSlice())
case "xattrs":
for key := iter.ReadObject(); key != ""; key = iter.ReadObject() {
count += len(iter.ReadStringAsSlice())
}
default:
iter.Skip()
}
}
}
break
}

buf.Grow(count)

getString := func(b []byte) string {
from := buf.Len()
buf.Write(b)
to := buf.Len()
return byteSliceAsString(buf.Bytes()[from:to])
}

pool := iter.Pool()
pool.ReturnIterator(iter)
iter = pool.BorrowIterator(manifest)

for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
if strings.ToLower(field) == "version" {
Expand All @@ -706,11 +670,11 @@ func unmarshalToc(manifest []byte) (*internal.TOC, error) {
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
switch strings.ToLower(field) {
case "type":
m.Type = getString(iter.ReadStringAsSlice())
m.Type = iter.ReadString()
case "name":
m.Name = getString(iter.ReadStringAsSlice())
m.Name = iter.ReadString()
case "linkname":
m.Linkname = getString(iter.ReadStringAsSlice())
m.Linkname = iter.ReadString()
case "mode":
m.Mode = iter.ReadInt64()
case "size":
Expand All @@ -720,19 +684,19 @@ func unmarshalToc(manifest []byte) (*internal.TOC, error) {
case "gid":
m.GID = iter.ReadInt()
case "modtime":
time, err := time.Parse(time.RFC3339, byteSliceAsString(iter.ReadStringAsSlice()))
time, err := time.Parse(time.RFC3339, iter.ReadString())
if err != nil {
return nil, err
}
m.ModTime = &time
case "accesstime":
time, err := time.Parse(time.RFC3339, byteSliceAsString(iter.ReadStringAsSlice()))
time, err := time.Parse(time.RFC3339, iter.ReadString())
if err != nil {
return nil, err
}
m.AccessTime = &time
case "changetime":
time, err := time.Parse(time.RFC3339, byteSliceAsString(iter.ReadStringAsSlice()))
time, err := time.Parse(time.RFC3339, iter.ReadString())
if err != nil {
return nil, err
}
Expand All @@ -742,7 +706,7 @@ func unmarshalToc(manifest []byte) (*internal.TOC, error) {
case "devminor":
m.Devminor = iter.ReadInt64()
case "digest":
m.Digest = getString(iter.ReadStringAsSlice())
m.Digest = iter.ReadString()
case "offset":
m.Offset = iter.ReadInt64()
case "endoffset":
Expand All @@ -752,14 +716,13 @@ func unmarshalToc(manifest []byte) (*internal.TOC, error) {
case "chunkoffset":
m.ChunkOffset = iter.ReadInt64()
case "chunkdigest":
m.ChunkDigest = getString(iter.ReadStringAsSlice())
m.ChunkDigest = iter.ReadString()
case "chunktype":
m.ChunkType = getString(iter.ReadStringAsSlice())
m.ChunkType = iter.ReadString()
case "xattrs":
m.Xattrs = make(map[string]string)
for key := iter.ReadObject(); key != ""; key = iter.ReadObject() {
value := iter.ReadStringAsSlice()
m.Xattrs[key] = getString(value)
m.Xattrs[key] = iter.ReadString()
}
default:
iter.Skip()
Expand All @@ -781,6 +744,5 @@ func unmarshalToc(manifest []byte) (*internal.TOC, error) {
return nil, fmt.Errorf("unexpected data after manifest")
}

toc.StringsBuf = buf
return &toc, nil
}
24 changes: 22 additions & 2 deletions pkg/chunked/cache_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ const jsonTOC = `
"chunkSize": 86252,
"chunkOffset": 17615,
"chunkDigest": "sha256:2a9d3f1b6b37abc8bb35eb8fa98b893a2a2447bcb01184c3bafc8c6b40da099d"
},
{
"type": "reg",
"name": "usr/lib/systemd/system/system-systemd\\x2dcryptsetup.slice",
"mode": 420,
"size": 468,
"modtime": "2024-03-03T18:04:57+01:00",
"accesstime": "0001-01-01T00:00:00Z",
"changetime": "0001-01-01T00:00:00Z",
"digest": "sha256:68dc6e85631e077f2bc751352459823844911b93b7ba2afd95d96c893222bb50",
"offset": 148185424,
"endOffset": 148185753
},
{
"type": "reg",
"name": "usr/lib/systemd/system/system-systemd\\x2dcryptsetup-hardlink.slice",
"linkName": "usr/lib/systemd/system/system-systemd\\x2dcryptsetup.slice"
}
]
}
Expand All @@ -65,7 +82,7 @@ func TestPrepareMetadata(t *testing.T) {
if err != nil {
t.Errorf("got error from prepareCacheFile: %v", err)
}
if len(toc) != 2 {
if len(toc) != 4 {
t.Error("prepareCacheFile returns the wrong length")
}
}
Expand Down Expand Up @@ -194,7 +211,7 @@ func TestReadCache(t *testing.T) {
func TestUnmarshalToc(t *testing.T) {
toc, err := unmarshalToc([]byte(jsonTOC))
assert.NoError(t, err)
assert.Equal(t, 4, len(toc.Entries))
assert.Equal(t, 6, len(toc.Entries))

_, err = unmarshalToc([]byte(jsonTOC + " \n\n\n\n "))
assert.NoError(t, err)
Expand All @@ -210,4 +227,7 @@ func TestUnmarshalToc(t *testing.T) {
assert.Error(t, err)
_, err = unmarshalToc([]byte(jsonTOC + "123"))
assert.Error(t, err)
assert.Equal(t, toc.Entries[4].Name, "usr/lib/systemd/system/system-systemd\\x2dcryptsetup.slice", "invalid name escaped")
assert.Equal(t, toc.Entries[5].Name, "usr/lib/systemd/system/system-systemd\\x2dcryptsetup-hardlink.slice", "invalid name escaped")
assert.Equal(t, toc.Entries[5].Linkname, "usr/lib/systemd/system/system-systemd\\x2dcryptsetup.slice", "invalid link name escaped")
}
3 changes: 0 additions & 3 deletions pkg/chunked/internal/compression.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ import (
type TOC struct {
Version int `json:"version"`
Entries []FileMetadata `json:"entries"`

// internal: used by unmarshalToc
StringsBuf bytes.Buffer `json:"-"`
}

type FileMetadata struct {
Expand Down

0 comments on commit a3d902f

Please sign in to comment.