1
1
mirror of https://github.com/wader/fq.git synced 2024-12-24 13:52:02 +03:00

makes dictionary key type checking more sensible

This commit is contained in:
David McDonald 2022-10-09 13:34:00 -05:00
parent ac86f9318b
commit b09d61162b

View File

@ -90,11 +90,15 @@ func decodeSize(d *decode.D, sms ...scalar.Mapper) uint64 {
return n return n
} }
func decodeItem(d *decode.D, p *plist) any { // decodeItem decodes an object from the plist, and assumes that the current
// seek position of the *decode.D is an object type tag. Returns a bool
// indicating whether or not a string was decoded, which is necssary for
// checking dictionary key type validity.
func decodeItem(d *decode.D, p *plist) bool {
m := d.FieldU4("type", elementTypeMap) m := d.FieldU4("type", elementTypeMap)
switch m { switch m {
case elementTypeNullOrBoolOrFill: case elementTypeNullOrBoolOrFill:
return d.FieldU4("value", scalar.UToScalar{ d.FieldU4("value", scalar.UToScalar{
null: scalar.S{Sym: nil}, null: scalar.S{Sym: nil},
boolTrue: scalar.S{Sym: true}, boolTrue: scalar.S{Sym: true},
boolFalse: scalar.S{Sym: false}, boolFalse: scalar.S{Sym: false},
@ -105,47 +109,48 @@ func decodeItem(d *decode.D, p *plist) any {
}) })
switch n { switch n {
case 1: case 1:
return d.FieldU8("value") d.FieldU8("value")
case 2: case 2:
return d.FieldU16("value") d.FieldU16("value")
case 4: case 4:
return d.FieldU32("value") d.FieldU32("value")
case 8: case 8:
return d.FieldS64("value") d.FieldS64("value")
case 16: case 16:
return d.FieldSBigInt("value", int(n*8)) d.FieldSBigInt("value", int(n*8))
default: default:
d.Errorf("invalid integer size %d", n) d.Errorf("invalid integer size %d", n)
return nil
} }
case elementTypeReal: case elementTypeReal:
n := 1 << decodeSize(d) n := 1 << decodeSize(d)
d.FieldValueU("size", uint64(n)) d.FieldValueU("size", uint64(n))
return d.FieldF("value", n*8) d.FieldF("value", n*8)
case elementTypeDate: case elementTypeDate:
n := 1 << decodeSize(d, d.AssertU(4, 8)) n := 1 << decodeSize(d, d.AssertU(4, 8))
d.FieldValueU("size", uint64(n)) d.FieldValueU("size", uint64(n))
return d.FieldF("value", n*8, scalar.DescriptionTimeFn(scalar.S.TryActualF, cocoaTimeEpochDate, time.RFC3339)) d.FieldF("value", n*8, scalar.DescriptionTimeFn(scalar.S.TryActualF, cocoaTimeEpochDate, time.RFC3339))
case elementTypeData: case elementTypeData:
n := decodeSize(d) n := decodeSize(d)
d.FieldValueU("size", n) d.FieldValueU("size", n)
return d.FieldRawLen("value", int64(n*8)) d.FieldRawLen("value", int64(n*8))
case elementTypeASCIIString: case elementTypeASCIIString:
n := decodeSize(d) n := decodeSize(d)
d.FieldValueU("size", n) d.FieldValueU("size", n)
return d.FieldUTF8("value", int(n)) d.FieldUTF8("value", int(n))
return true
case elementTypeUnicodeString: case elementTypeUnicodeString:
n := decodeSize(d) n := decodeSize(d)
d.FieldValueU("size", n) d.FieldValueU("size", n)
return d.FieldUTF16("value", int(n)) d.FieldUTF16("value", int(n))
return true
case elementTypeUID: case elementTypeUID:
n := decodeSize(d) n := decodeSize(d)
d.FieldValueU("size", n) d.FieldValueU("size", n)
return d.FieldUBigInt("value", int(n)).Uint64() d.FieldUBigInt("value", int(n)).Uint64()
case elementTypeArray: case elementTypeArray:
n := decodeSize(d) n := decodeSize(d)
d.FieldValueU("size", n) d.FieldValueU("size", n)
return d.FieldStructNArray("entries", "entry", int64(n), d.FieldStructNArray("entries", "entry", int64(n),
func(d *decode.D) { func(d *decode.D) {
idx := d.FieldU("object_index", int(p.t.objRefSize)*8) idx := d.FieldU("object_index", int(p.t.objRefSize)*8)
p.decodeReference(d, idx) p.decodeReference(d, idx)
@ -153,7 +158,7 @@ func decodeItem(d *decode.D, p *plist) any {
case elementTypeSet: case elementTypeSet:
n := decodeSize(d) n := decodeSize(d)
d.FieldValueU("size", n) d.FieldValueU("size", n)
return d.FieldStructNArray("entries", "entry", int64(n), d.FieldStructNArray("entries", "entry", int64(n),
func(d *decode.D) { func(d *decode.D) {
idx := d.FieldU("object_index", int(p.t.objRefSize)*8) idx := d.FieldU("object_index", int(p.t.objRefSize)*8)
p.decodeReference(d, idx) p.decodeReference(d, idx)
@ -161,7 +166,7 @@ func decodeItem(d *decode.D, p *plist) any {
case elementTypeDict: case elementTypeDict:
n := decodeSize(d) n := decodeSize(d)
d.FieldValueU("size", n) d.FieldValueU("size", n)
return d.FieldStructNArray("entries", "entry", int64(n), d.FieldStructNArray("entries", "entry", int64(n),
func(d *decode.D) { func(d *decode.D) {
var ki, vi uint64 var ki, vi uint64
ki = d.FieldU("key_index", int(p.t.objRefSize)*8) ki = d.FieldU("key_index", int(p.t.objRefSize)*8)
@ -169,8 +174,7 @@ func decodeItem(d *decode.D, p *plist) any {
vi = d.FieldU("value_index", int(p.t.objRefSize)*8) vi = d.FieldU("value_index", int(p.t.objRefSize)*8)
}) })
d.FieldStruct("key", func(d *decode.D) { d.FieldStruct("key", func(d *decode.D) {
k := p.decodeReference(d, ki) if k := p.decodeReference(d, ki); !k {
if _, ok := k.(string); !ok {
d.Errorf("non-string key in dictionary") d.Errorf("non-string key in dictionary")
} }
}) })
@ -180,20 +184,24 @@ func decodeItem(d *decode.D, p *plist) any {
}) })
default: default:
d.Errorf("unknown type marker: %d", m) d.Errorf("unknown type marker: %d", m)
return nil
} }
return false
} }
func (pl *plist) decodeReference(d *decode.D, idx uint64) any { // decodeReference looks up and decodes an object based on its index in the
// offset table. Returns a bool indicating whether or not the decoded item is
// a string (necessary for checking dictionary key validity).
func (pl *plist) decodeReference(d *decode.D, idx uint64) bool {
if idx > uint64(len(pl.o)) { if idx > uint64(len(pl.o)) {
// prevent a panic // prevent a panic
d.Errorf("index %d out of bounds for object table size %d", idx, len(pl.o)) d.Errorf("index %d out of bounds for object table size %d", idx, len(pl.o))
return nil return false
} }
if pl.indexIsInStack(idx) { if pl.indexIsInStack(idx) {
d.Fatalf("recursion detected: object %d already decoded in stack %v", idx, pl.objectStack) d.Fatalf("recursion detected: object %d already decoded in stack %v", idx, pl.objectStack)
return nil return false
} }
pl.pushIndex(idx) pl.pushIndex(idx)
@ -204,12 +212,12 @@ func (pl *plist) decodeReference(d *decode.D, idx uint64) any {
idx, itemOffset, pl.t.offsetTableStart) idx, itemOffset, pl.t.offsetTableStart)
} }
var item any var isString bool
d.SeekAbs(int64(itemOffset*8), func(d *decode.D) { d.SeekAbs(int64(itemOffset*8), func(d *decode.D) {
item = decodeItem(d, pl) isString = decodeItem(d, pl)
}) })
pl.popIndex() pl.popIndex()
return item return isString
} }
type trailer struct { type trailer struct {