Skip to content

Commit 377cee5

Browse files
blahspamsbowman
andauthored
fix: segmentation_upids with certain ISO-8859-1 characters decoded incorrectly
* Handle ASCII-encoded segmentation UPIDs correctly * fix: move test and more complete fix for ascii chars * chore: cleanup some tmp changes * docs: add some comments around the Latin <-> UTF8 process * docs: Update SegmentationUPID.ASCIIValue() * chore: address feedback --------- Co-authored-by: Sean Bowman <[email protected]>
1 parent 0992f43 commit 377cee5

10 files changed

+156
-49
lines changed

.pre-commit-config.yaml

+12-9
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,22 @@ repos:
99
- id: end-of-file-fixer
1010
- id: trailing-whitespace
1111
args: [--markdown-linebreak-ext=md]
12-
- repo: https://github.com/dnephin/pre-commit-golang
13-
rev: v0.5.1
12+
- repo: https://github.com/tekwizely/pre-commit-golang
13+
rev: v1.0.0-rc.1
1414
hooks:
1515
- id: go-fmt
16-
- id: go-vet
17-
- id: golangci-lint
18-
- id: go-unit-tests
19-
- id: go-build
16+
- id: go-build-mod
2017
- id: go-mod-tidy
21-
- repo: https://github.com/sirosen/texthooks
22-
rev: 0.5.0
18+
- id: golangci-lint-mod
19+
- repo: https://github.com/adrienverge/yamllint.git
20+
rev: v1.32.0
2321
hooks:
24-
- id: fix-smartquotes
22+
- id: yamllint
23+
args: [--format, colored]
24+
- repo: https://github.com/zricethezav/gitleaks
25+
rev: v8.17.0
26+
hooks:
27+
- id: gitleaks
2528
- repo: https://github.com/compilerla/conventional-pre-commit
2629
rev: v2.3.0
2730
hooks:

CODE_OF_CONDUCT.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi
7171
available at [http://contributor-covenant.org/version/1/4][version]
7272

7373
[homepage]: http://contributor-covenant.org
74-
[version]: http://contributor-covenant.org/version/1/4/
74+
[version]: http://contributor-covenant.org/version/1/4/

CONTRIBUTING.md

-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,3 @@ If your change is adding your newly released Comcast Open Source project to http
3232
Before Comcast merges your code into the project you must sign the [Comcast Contributor License Agreement (CLA)](https://gist.github.com/ComcastOSS/a7b8933dd8e368535378cda25c92d19a).
3333

3434
If you haven't previously signed a Comcast CLA, you'll automatically be asked to when you open a pull request. Alternatively, we can send you a PDF that you can sign and scan back to us. Please create a new GitHub issue to request a PDF version of the CLA.
35-

NOTICE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
SCTE-35
1+
SCTE-35
22

33
Copyright 2021 Comcast Cable Communications Management, LLC
44

examples/README.md

-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ To execute an example from the command line:
88
```shell
99
$ go run ./examples/simple_decode
1010
```
11-

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/bamiaux/iobit v0.0.0-20170418073505-498159a04883
77
github.com/spf13/cobra v1.7.0
88
github.com/stretchr/testify v1.8.4
9+
golang.org/x/text v0.10.0
910
)
1011

1112
require (

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
1919
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
2020
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
2121
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
22+
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
23+
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
2224
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2325
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
2426
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

pkg/scte35/scte35_test.go

+112-18
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"encoding/binary"
2121
"encoding/json"
2222
"encoding/xml"
23-
"fmt"
2423
"io"
2524
"os"
2625
"testing"
@@ -30,6 +29,11 @@ import (
3029
"github.com/stretchr/testify/require"
3130
)
3231

32+
func TestMain(m *testing.M) {
33+
scte35.Logger.SetOutput(os.Stderr)
34+
os.Exit(m.Run())
35+
}
36+
3337
func TestDecodeBase64(t *testing.T) {
3438
scte35.Logger.SetOutput(os.Stderr)
3539
defer scte35.Logger.SetOutput(io.Discard)
@@ -63,7 +67,7 @@ func TestDecodeBase64(t *testing.T) {
6367
SegmentationTypeID: scte35.SegmentationTypeProviderPOStart,
6468
SegmentationDuration: uint64ptr(0x0001a599b0),
6569
SegmentationUPIDs: []scte35.SegmentationUPID{
66-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca0a18a)),
70+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca0a18a)),
6771
},
6872
SegmentNum: 2,
6973
},
@@ -118,7 +122,7 @@ func TestDecodeBase64(t *testing.T) {
118122
SegmentationEventID: 0x4800008e,
119123
SegmentationTypeID: scte35.SegmentationTypeProviderPOEnd,
120124
SegmentationUPIDs: []scte35.SegmentationUPID{
121-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca0a18a)),
125+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca0a18a)),
122126
},
123127
SegmentNum: 2,
124128
},
@@ -147,7 +151,7 @@ func TestDecodeBase64(t *testing.T) {
147151
SegmentationEventID: 0x48000018,
148152
SegmentationTypeID: scte35.SegmentationTypeProgramEnd,
149153
SegmentationUPIDs: []scte35.SegmentationUPID{
150-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ccbc344)),
154+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ccbc344)),
151155
},
152156
},
153157
&scte35.SegmentationDescriptor{
@@ -160,7 +164,7 @@ func TestDecodeBase64(t *testing.T) {
160164
SegmentationEventID: 0x48000019,
161165
SegmentationTypeID: scte35.SegmentationTypeProgramStart,
162166
SegmentationUPIDs: []scte35.SegmentationUPID{
163-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca4dba0)),
167+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca4dba0)),
164168
},
165169
},
166170
},
@@ -188,7 +192,7 @@ func TestDecodeBase64(t *testing.T) {
188192
SegmentationEventID: 0x48000008,
189193
SegmentationTypeID: scte35.SegmentationTypeProgramOverlapStart,
190194
SegmentationUPIDs: []scte35.SegmentationUPID{
191-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca56cf5)),
195+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca56cf5)),
192196
},
193197
},
194198
},
@@ -216,7 +220,7 @@ func TestDecodeBase64(t *testing.T) {
216220
SegmentationEventID: 0x4800000a,
217221
SegmentationTypeID: scte35.SegmentationTypeProgramBlackoutOverride,
218222
SegmentationUPIDs: []scte35.SegmentationUPID{
219-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca0a1e3)),
223+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca0a1e3)),
220224
},
221225
},
222226
&scte35.SegmentationDescriptor{
@@ -229,7 +233,7 @@ func TestDecodeBase64(t *testing.T) {
229233
SegmentationEventID: 0x48000009,
230234
SegmentationTypeID: scte35.SegmentationTypeProgramEnd,
231235
SegmentationUPIDs: []scte35.SegmentationUPID{
232-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca0a18a)),
236+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca0a18a)),
233237
},
234238
},
235239
},
@@ -257,7 +261,7 @@ func TestDecodeBase64(t *testing.T) {
257261
SegmentationEventID: 0x48000007,
258262
SegmentationTypeID: scte35.SegmentationTypeProgramEnd,
259263
SegmentationUPIDs: []scte35.SegmentationUPID{
260-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca56c97)),
264+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca56c97)),
261265
},
262266
},
263267
},
@@ -285,7 +289,7 @@ func TestDecodeBase64(t *testing.T) {
285289
SegmentationEventID: 0x480000ad,
286290
SegmentationTypeID: scte35.SegmentationTypeProviderPOEnd,
287291
SegmentationUPIDs: []scte35.SegmentationUPID{
288-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002cb2d79d)),
292+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002cb2d79d)),
289293
},
290294
SegmentNum: 2,
291295
},
@@ -299,7 +303,7 @@ func TestDecodeBase64(t *testing.T) {
299303
SegmentationEventID: 0x48000026,
300304
SegmentationTypeID: scte35.SegmentationTypeProgramEnd,
301305
SegmentationUPIDs: []scte35.SegmentationUPID{
302-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002cb2d79d)),
306+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002cb2d79d)),
303307
},
304308
},
305309
&scte35.SegmentationDescriptor{
@@ -312,7 +316,7 @@ func TestDecodeBase64(t *testing.T) {
312316
SegmentationEventID: 0x48000027,
313317
SegmentationTypeID: scte35.SegmentationTypeProgramStart,
314318
SegmentationUPIDs: []scte35.SegmentationUPID{
315-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002cb2d7b3)),
319+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002cb2d7b3)),
316320
},
317321
},
318322
},
@@ -388,7 +392,7 @@ func TestDecodeBase64(t *testing.T) {
388392
},
389393
"Empty String": {
390394
binary: "",
391-
err: fmt.Errorf("splice_info_section: %w", scte35.ErrBufferOverflow),
395+
err: scte35.ErrBufferOverflow,
392396
},
393397
"Invalid Base64 Encoding": {
394398
binary: "/DBaf%^",
@@ -468,7 +472,7 @@ func TestDecodeBase64(t *testing.T) {
468472
},
469473
"SpliceInsert Time Specified With Invalid Component Count": {
470474
binary: "FkC1lwP3uTQD0VvxHwVBEH89G6B7VjzaZ9eNuyUF9q8pYAIXsRM9ZpDCczBeDbytQhXkssQstGJVGcvjZ3tiIMULiA4BpRHlzLGFa0q6aVMtzk8ZRUeLcxtKibgVOKBBnkCbOQyhSflFiDkrAAIp+Fk+VRsByTSkPN3RvyK+lWcjHElhwa9hNFcAy4dm3DdeRXnrD3I2mISNc7DkgS0ReotPyp94FV77xMHT4D7SYL48XU20UM4bgg==",
471-
err: fmt.Errorf("splice_insert: %w", scte35.ErrBufferOverflow),
475+
err: scte35.ErrBufferOverflow,
472476
},
473477
"Signal with non-CUEI descriptor": {
474478
binary: "/DBPAAAAAAAAAP/wBQb/Gq9LggA5AAVTQVBTCwIwQ1VFSf////9//wAAFI4PDxx1cm46bmJjdW5pLmNvbTpicmM6NDk5ODY2NDM0MQoBbM98zw==",
@@ -507,7 +511,7 @@ func TestDecodeBase64(t *testing.T) {
507511
},
508512
"Invalid CRC_32": {
509513
binary: "/DA4AAAAAAAAAP/wFAUABDEAf+//mWEhzP4Azf5gAQAAAAATAhFDVUVJAAAAAX+/AQIwNAEAAKeYO3Q=",
510-
err: fmt.Errorf("splice_info_section: %w", scte35.ErrCRC32Invalid),
514+
err: scte35.ErrCRC32Invalid,
511515
},
512516
"Alignment Stuffing without Encryption": {
513517
binary: "/DAeAAAAAAAAAP///wViAA/nf18ACQAAAAAskJv+YPtE",
@@ -523,13 +527,103 @@ func TestDecodeBase64(t *testing.T) {
523527
},
524528
legacy: true, // binary wont match because of stuffing
525529
},
530+
"UPID with Valid ASCII Invalid UTF8": {
531+
binary: "/DDHAAAAABc0AP/wBQb/tVo+agCxAhdDVUVJQA4hwH+fCAgAAAAAPj6IcCMAAAIXQ1VFSUAOI1x/nwgIAAAAAD4+iHARAAACF0NVRUlADiHgf58ICAAAAAA+Poi2EAAAAhxDVUVJQA4hyn/fAABSlKwICAAAAAA+Poi2IgAAAkZDVUVJQA4h1n/PAABSlKwNMgoMFHf5uXs0AAAAAAAADhh0eXBlPUxBJmR1cj02MDAwMCZ0aWVy/DDHAAAAAAAAAP8ABQb/HPCt2w==",
532+
expected: scte35.SpliceInfoSection{
533+
SpliceCommand: &scte35.TimeSignal{
534+
SpliceTime: scte35.SpliceTime{
535+
PTSTime: uint64ptr(7337557610),
536+
},
537+
},
538+
SpliceDescriptors: scte35.SpliceDescriptors{
539+
&scte35.SegmentationDescriptor{
540+
SegmentationEventID: uint32(1074667968),
541+
SegmentationTypeID: scte35.SegmentationTypeBreakEnd,
542+
DeliveryRestrictions: &scte35.DeliveryRestrictions{
543+
ArchiveAllowedFlag: true,
544+
WebDeliveryAllowedFlag: true,
545+
NoRegionalBlackoutFlag: true,
546+
DeviceRestrictions: 3,
547+
},
548+
SegmentationUPIDs: []scte35.SegmentationUPID{
549+
{Type: scte35.SegmentationUPIDTypeTI, Value: "1044285552"},
550+
},
551+
},
552+
&scte35.SegmentationDescriptor{
553+
SegmentationEventID: uint32(1074668380),
554+
SegmentationTypeID: scte35.SegmentationTypeProgramEnd,
555+
DeliveryRestrictions: &scte35.DeliveryRestrictions{
556+
ArchiveAllowedFlag: true,
557+
WebDeliveryAllowedFlag: true,
558+
NoRegionalBlackoutFlag: true,
559+
DeviceRestrictions: 3,
560+
},
561+
SegmentationUPIDs: []scte35.SegmentationUPID{
562+
{Type: scte35.SegmentationUPIDTypeTI, Value: "1044285552"},
563+
},
564+
},
565+
&scte35.SegmentationDescriptor{
566+
SegmentationEventID: uint32(1074668000),
567+
SegmentationTypeID: scte35.SegmentationTypeProgramStart,
568+
DeliveryRestrictions: &scte35.DeliveryRestrictions{
569+
ArchiveAllowedFlag: true,
570+
WebDeliveryAllowedFlag: true,
571+
NoRegionalBlackoutFlag: true,
572+
DeviceRestrictions: 3,
573+
},
574+
SegmentationUPIDs: []scte35.SegmentationUPID{
575+
{Type: scte35.SegmentationUPIDTypeTI, Value: "1044285622"},
576+
},
577+
},
578+
&scte35.SegmentationDescriptor{
579+
SegmentationEventID: uint32(1074667978),
580+
SegmentationDuration: uint64ptr(5412012),
581+
SegmentationTypeID: scte35.SegmentationTypeBreakStart,
582+
DeliveryRestrictions: &scte35.DeliveryRestrictions{
583+
ArchiveAllowedFlag: true,
584+
WebDeliveryAllowedFlag: true,
585+
NoRegionalBlackoutFlag: true,
586+
DeviceRestrictions: 3,
587+
},
588+
SegmentationUPIDs: []scte35.SegmentationUPID{
589+
{Type: scte35.SegmentationUPIDTypeTI, Value: "1044285622"},
590+
},
591+
},
592+
&scte35.SegmentationDescriptor{
593+
SegmentationEventID: uint32(1074667990),
594+
SegmentationTypeID: 0x05,
595+
SegmentationDuration: uint64ptr(5412012),
596+
SegmentNum: 6,
597+
SegmentsExpected: 255,
598+
DeliveryRestrictions: &scte35.DeliveryRestrictions{
599+
ArchiveAllowedFlag: true,
600+
WebDeliveryAllowedFlag: false,
601+
NoRegionalBlackoutFlag: true,
602+
DeviceRestrictions: 3,
603+
},
604+
SegmentationUPIDs: []scte35.SegmentationUPID{
605+
{Type: scte35.SegmentationUPIDTypeEIDR, Value: "10.5239/F9B9-7B34-0000-0000-0000"},
606+
{Type: scte35.SegmentationUPIDTypeADS, Value: "type=LA&dur=60000&tierü0"},
607+
{Type: uint32(199)},
608+
{Type: uint32(0)},
609+
{Type: uint32(0)},
610+
{Type: uint32(0)},
611+
{Type: uint32(255)},
612+
},
613+
},
614+
},
615+
PTSAdjustment: uint64(5940),
616+
Tier: 4095,
617+
SAPType: 3,
618+
},
619+
},
526620
}
527621

528622
for k, c := range cases {
529623
t.Run(k, func(t *testing.T) {
530624
// decode the binary
531625
sis, err := scte35.DecodeBase64(c.binary)
532-
require.Equal(t, c.err, err)
626+
require.ErrorIs(t, err, c.err)
533627
if err != nil {
534628
return
535629
}
@@ -591,7 +685,7 @@ func TestDecodeHex(t *testing.T) {
591685
SegmentationTypeID: scte35.SegmentationTypeProviderPOStart,
592686
SegmentationDuration: uint64ptr(0x0001a599b0),
593687
SegmentationUPIDs: []scte35.SegmentationUPID{
594-
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, bytes(0x000000002ca0a18a)),
688+
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, toBytes(0x000000002ca0a18a)),
595689
},
596690
SegmentNum: 2,
597691
},
@@ -686,7 +780,7 @@ func TestTicksToDuration(t *testing.T) {
686780

687781
// helper func to make test life a bit easier
688782

689-
func bytes(i uint64) []byte {
783+
func toBytes(i uint64) []byte {
690784
b := make([]byte, 8)
691785
binary.BigEndian.PutUint64(b, i)
692786
return b

pkg/scte35/segmentation_descriptor.go

+8
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ func (sd *SegmentationDescriptor) SegmentationUpidLength() int {
326326

327327
// decode updates this splice_descriptor from binary.
328328
func (sd *SegmentationDescriptor) decode(b []byte) error {
329+
var err error
330+
329331
r := iobit.NewReader(b)
330332
r.Skip(8) // splice_descriptor_tag
331333
r.Skip(8) // descriptor_length
@@ -378,6 +380,9 @@ func (sd *SegmentationDescriptor) decode(b []byte) error {
378380
upidType := upidr.Uint32(8)
379381
upidLength := int(upidr.Uint32(8))
380382
upidValue := upidr.Bytes(upidLength)
383+
if len(upidValue) < upidLength {
384+
Logger.Printf("Cannot read value for segmentation_upid_type %d; %d of %d bytes remaining.", upidType, len(upidValue), upidLength)
385+
}
381386
sd.SegmentationUPIDs = append(
382387
sd.SegmentationUPIDs,
383388
NewSegmentationUPID(upidType, upidValue),
@@ -406,6 +411,9 @@ func (sd *SegmentationDescriptor) decode(b []byte) error {
406411
}
407412
}
408413

414+
if err != nil {
415+
return err
416+
}
409417
if err := readerError(r); err != nil {
410418
return fmt.Errorf("segmentation_descriptor: %w", err)
411419
}

0 commit comments

Comments
 (0)