diff --git a/cmd/core/display_utils.go b/cmd/core/display_utils.go index 00231942..08da7fb9 100644 --- a/cmd/core/display_utils.go +++ b/cmd/core/display_utils.go @@ -323,6 +323,12 @@ func displayFar(sb *strings.Builder, far *ie.IE) { } func displayPdr(sb *strings.Builder, pdr *ie.IE) { + defer func() { + if r := recover(); r != nil { + log.Warn().Msgf("recovered from panic while formatting PDR for logging: %v", r) + } + }() + pdrId, _ := pdr.PDRID() fmt.Fprintf(sb, "PDR ID: %d \n", pdrId) diff --git a/cmd/core/display_utils_test.go b/cmd/core/display_utils_test.go new file mode 100644 index 00000000..daf5b322 --- /dev/null +++ b/cmd/core/display_utils_test.go @@ -0,0 +1,27 @@ +package core + +import ( + "strings" + "testing" + + "github.com/wmnsk/go-pfcp/ie" +) + +// TestDisplayPdrMalformedSdfFilter pins displayPdr against a PDI whose SDF +// Filter claims a Flow-Description length far longer than the bytes actually +// present. go-pfcp's SDFFilterFields.UnmarshalBinary slices past the buffer +// in that case and panics; displayPdr is a logging path and must not take +// the UPF down with it. +func TestDisplayPdrMalformedSdfFilter(t *testing.T) { + // Flags=0x01 (FD present), spare octet, FDLength=0xFFFE, one byte of + // actual description. + malformedSdfFilter := ie.New(ie.SDFFilter, []byte{0x01, 0x00, 0xFF, 0xFE, 0x41}) + pdi := ie.NewPDI( + ie.NewSourceInterface(ie.SrcInterfaceAccess), + malformedSdfFilter, + ) + pdr := ie.NewCreatePDR(ie.NewPDRID(1), pdi) + + var sb strings.Builder + displayPdr(&sb, pdr) +}