mirror of
https://github.com/wader/fq.git
synced 2024-12-23 21:31:33 +03:00
makes dictionary key type checking more sensible
This commit is contained in:
parent
ac86f9318b
commit
b09d61162b
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user