Skip to content

Commit 51517b3

Browse files
committed
fix foo
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
1 parent aa2f822 commit 51517b3

3 files changed

Lines changed: 104 additions & 2 deletions

File tree

app/cli/pkg/action/workflow_run_describe.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"fmt"
2424
"sort"
2525
"strings"
26+
"unicode/utf8"
2627

2728
pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1"
2829
"github.com/chainloop-dev/chainloop/pkg/attestation/renderer/chainloop"
@@ -76,6 +77,7 @@ type PolicyEvaluationStatus struct {
7677
type Material struct {
7778
Name string `json:"name"`
7879
Value string `json:"value"`
80+
RawValue []byte `json:"raw_value,omitempty"`
7981
Hash string `json:"hash"`
8082
Tag string `json:"tag"`
8183
Filename string `json:"filename"`
@@ -318,13 +320,18 @@ func materialPBToAction(in *pb.AttestationItem_Material) *Material {
318320
var value string
319321
if len(in.GetRawValue()) > 0 {
320322
value = string(in.GetRawValue())
323+
if !utf8.Valid(in.GetRawValue()) {
324+
value = ""
325+
}
321326
} else {
322327
value = in.GetValue() //nolint:staticcheck // fallback for older servers
323328
}
324329

325330
m := &Material{
326-
Name: in.Name,
331+
Name: in.Name,
332+
// kept for compatibility in case we have users that are still using the string value field
327333
Value: value,
334+
RawValue: in.GetRawValue(),
328335
Type: in.Type,
329336
Hash: in.Hash,
330337
Tag: in.Tag,

app/controlplane/pkg/biz/organization.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ func (uc *OrganizationUseCase) CreateWithRandomName(ctx context.Context, opts ..
142142
uc.logger.Debugw("msg", "Org exists!", "name", name)
143143
continue
144144
}
145-
uc.logger.Debugw("msg", "BOOM", "name", name, "err", err)
146145
return nil, err
147146
}
148147

pkg/attestation/renderer/chainloop/v02_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,102 @@ func TestNormalizeMaterial(t *testing.T) {
300300
}
301301
}
302302

303+
// TestBinaryContentStructRoundTrip verifies that binary (non-UTF-8) content in
304+
// ResourceDescriptor.Content survives the structpb.Struct round-trip that happens
305+
// during predicate() → extractPredicate(): json.Marshal → protojson.Unmarshal(Struct) →
306+
// protojson.Marshal(Struct) → json.Unmarshal.
307+
func TestBinaryContentStructRoundTrip(t *testing.T) {
308+
testCases := []struct {
309+
name string
310+
content []byte
311+
}{
312+
{
313+
name: "null bytes and high bytes",
314+
content: []byte{0xff, 0xfe, 0x00, 0x01, 0x80, 0x7f},
315+
},
316+
{
317+
name: "ELF header",
318+
content: []byte{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00},
319+
},
320+
{
321+
name: "all byte values",
322+
content: func() []byte {
323+
b := make([]byte, 256)
324+
for i := range b {
325+
b[i] = byte(i)
326+
}
327+
return b
328+
}(),
329+
},
330+
{
331+
name: "valid UTF-8 text",
332+
content: []byte("hello world"),
333+
},
334+
{
335+
name: "large binary payload",
336+
content: func() []byte {
337+
b := make([]byte, 64*1024)
338+
for i := range b {
339+
b[i] = byte(i % 251)
340+
}
341+
return b
342+
}(),
343+
},
344+
}
345+
346+
for _, tc := range testCases {
347+
t.Run(tc.name, func(t *testing.T) {
348+
// Build a minimal predicate with one inline artifact material
349+
original := &ProvenancePredicateV02{
350+
ProvenancePredicateCommon: &ProvenancePredicateCommon{},
351+
Materials: []*intoto.ResourceDescriptor{
352+
{
353+
Name: "binary.bin",
354+
Annotations: mapToStruct(t, map[string]interface{}{
355+
"chainloop.material.name": "test-binary",
356+
"chainloop.material.type": "ARTIFACT",
357+
"chainloop.material.cas.inline": true,
358+
}),
359+
Digest: map[string]string{"sha256": "deadbeef"},
360+
Content: tc.content,
361+
},
362+
},
363+
}
364+
365+
// === Step 1: predicate() path ===
366+
// json.Marshal base64-encodes []byte fields
367+
predicateJSON, err := json.Marshal(original)
368+
require.NoError(t, err)
369+
370+
// protojson.Unmarshal stores the base64 string in Struct
371+
predStruct := &structpb.Struct{}
372+
err = protojson.Unmarshal(predicateJSON, predStruct)
373+
require.NoError(t, err)
374+
375+
// === Step 2: extractPredicate() path ===
376+
// protojson.Marshal outputs the Struct as JSON
377+
roundTrippedJSON, err := protojson.Marshal(predStruct)
378+
require.NoError(t, err)
379+
380+
// json.Unmarshal decodes base64 back into []byte
381+
var restored ProvenancePredicateV02
382+
err = json.Unmarshal(roundTrippedJSON, &restored)
383+
require.NoError(t, err)
384+
385+
require.Len(t, restored.Materials, 1)
386+
assert.Equal(t, tc.content, restored.Materials[0].Content,
387+
"binary content should survive structpb.Struct round-trip")
388+
389+
// === Step 3: normalizeMaterial() ===
390+
normalized, err := normalizeMaterial(restored.Materials[0])
391+
require.NoError(t, err)
392+
assert.Equal(t, tc.content, normalized.Value,
393+
"binary content should survive normalization")
394+
assert.True(t, normalized.EmbeddedInline)
395+
})
396+
}
397+
}
398+
303399
func TestStructValueToString(t *testing.T) {
304400
testCases := []struct {
305401
name string

0 commit comments

Comments
 (0)