diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/align.go | 43 | ||||
| -rw-r--r-- | sys/decl.go | 13 | ||||
| -rw-r--r-- | sys/test.txt | 120 |
3 files changed, 145 insertions, 31 deletions
diff --git a/sys/align.go b/sys/align.go index 8b9e1a3c2..3c672b83e 100644 --- a/sys/align.go +++ b/sys/align.go @@ -22,6 +22,7 @@ func initAlign() { rec(f) } markBitfields(t1) + markVarlen(t1) addAlignment(t1) } case *UnionType: @@ -76,13 +77,38 @@ func markBitfields(t *StructType) { } } +func markVarlen(t *StructType) { + for i, f := range t.Fields { + if at, ok := f.(*StructType); ok && at.Varlen { + t.Varlen = true + } + if at, ok := f.(*UnionType); ok && at.Varlen { + t.Varlen = true + } + if at, ok := f.(*ArrayType); ok && (at.Kind == ArrayRandLen || (at.Kind == ArrayRangeLen && at.RangeBegin != at.RangeEnd)) { + t.Varlen = true + } + if at, ok := f.(*BufferType); ok && (at.Kind == BufferBlobRand || (at.Kind == BufferBlobRange && at.RangeBegin != at.RangeEnd)) { + t.Varlen = true + } + if !t.packed && t.Varlen && i != len(t.Fields)-1 { + panic(fmt.Sprintf("variable length field %+v in the middle of a struct %+v", f, t)) + } + } +} + func addAlignment(t *StructType) { if t.packed { + // If a struct is packed, statically sized and has explicitly set alignment, add a padding. + if !t.Varlen && t.align != 0 && t.Size()%t.align != 0 { + pad := t.align - t.Size()%t.align + t.Fields = append(t.Fields, makePad(pad)) + } return } var fields []Type - var off, align uintptr - varLen := false + var off uintptr + align := t.align for i, f := range t.Fields { a := f.Align() if align < a { @@ -97,21 +123,12 @@ func addAlignment(t *StructType) { } } fields = append(fields, f) - if at, ok := f.(*ArrayType); ok && (at.Kind == ArrayRandLen || (at.Kind == ArrayRangeLen && at.RangeBegin != at.RangeEnd)) { - varLen = true - } - if at, ok := f.(*BufferType); ok && (at.Kind == BufferBlobRand || (at.Kind == BufferBlobRange && at.RangeBegin != at.RangeEnd)) { - varLen = true - } - if varLen && i != len(t.Fields)-1 { - panic("embed array in middle of a struct") - } - if (f.BitfieldLength() == 0 || f.BitfieldLast()) && !varLen { + if (f.BitfieldLength() == 0 || f.BitfieldLast()) && !t.Varlen { // Increase offset if the current field is not a bitfield or it's the last bitfield in a set. off += f.Size() } } - if align != 0 && off%align != 0 && !varLen { + if align != 0 && off%align != 0 && !t.Varlen { pad := align - off%align off += pad fields = append(fields, makePad(pad)) diff --git a/sys/decl.go b/sys/decl.go index 9c7887f99..08df93dd2 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -222,6 +222,7 @@ type BufferType struct { Text TextKind // for BufferText SubKind string Values []string // possible values for BufferString kind + Length uintptr // max string length for BufferString kind } func (t *BufferType) Size() uintptr { @@ -292,6 +293,7 @@ func (t *PtrType) Align() uintptr { type StructType struct { TypeCommon Fields []Type + Varlen bool padded bool packed bool align uintptr @@ -303,7 +305,9 @@ func (t *StructType) Size() uintptr { } var size uintptr for _, f := range t.Fields { - size += f.Size() + if f.BitfieldLength() == 0 || f.BitfieldLast() { + size += f.Size() + } } return size } @@ -312,6 +316,9 @@ func (t *StructType) Align() uintptr { if t.align != 0 { return t.align // overrided by user attribute } + if t.packed { + return 1 + } var align uintptr for _, f := range t.Fields { if a1 := f.Align(); align < a1 { @@ -324,11 +331,11 @@ func (t *StructType) Align() uintptr { type UnionType struct { TypeCommon Options []Type - varlen bool + Varlen bool } func (t *UnionType) Size() uintptr { - if t.varlen { + if t.Varlen { panic("union size is not statically known") } size := t.Options[0].Size() diff --git a/sys/test.txt b/sys/test.txt index aa9ea1ab0..68ca85db8 100644 --- a/sys/test.txt +++ b/sys/test.txt @@ -6,16 +6,23 @@ syz_test() # Integer types. + syz_test$int(a0 intptr, a1 int8, a2 int16, a3 int32, a4 int64) # Opt arguments + syz_test$opt0(a0 intptr[opt]) syz_test$opt1(a0 ptr[in, intptr, opt]) syz_test$opt2(a0 vma[opt]) -# Struct alignment. +# Alignment and padding + syz_test$align0(a0 ptr[in, syz_align0]) syz_test$align1(a0 ptr[in, syz_align1]) +syz_test$align2(a0 ptr[in, syz_align2]) +syz_test$align3(a0 ptr[in, syz_align3]) +syz_test$align4(a0 ptr[in, syz_align4]) +syz_test$align5(a0 ptr[in, syz_align5]) syz_align0 { f0 int16 @@ -33,22 +40,93 @@ syz_align1 { f4 int64 } [packed] -# Unions. +syz_align2_packed { + f0 array[int16, 1] +} [packed] -syz_test$union0(a0 ptr[in, syz_union_struct]) +syz_align2_not_packed { + f0 array[int16, 1] +} -syz_union_struct { - f int64 - u syz_union0 +syz_align2 { + f0 int8 + f1 syz_align2_packed + f2 syz_align2_not_packed +} + +syz_align3_noalign { + f0 int8 +} + +syz_align3_align4 { + f0 int8 +} [align_4] + +syz_align3 { + f0 int8 + f1 syz_align3_noalign + f2 syz_align3_align4 +} + +syz_align4_internal { + f0 int8 + f1 int16 +} [packed, align_4] + +syz_align4 { + f0 syz_align4_internal + f1 int8 +} + +syz_align5_internal { + f0 int64 + f1 array[int16, 0:3] } +syz_align5 { + f0 syz_align5_internal + f1 syz_align5_internal + f2 int8 +} [packed] + +# Unions + +syz_test$union0(a0 ptr[in, syz_union0_struct]) +syz_test$union1(a0 ptr[in, syz_union1_struct]) +syz_test$union2(a0 ptr[in, syz_union2_struct]) + syz_union0 [ f0 int64 f1 array[int64, 10] f2 int8 ] -# Arrays. +syz_union0_struct { + f int64 + u syz_union0 +} + +syz_union1 [ + f0 int64 + f1 int32 +] + +syz_union1_struct { + f0 syz_union1 + f1 int8 +} [packed] + +syz_union2 [ + f0 int64 + f1 int32 +] [varlen] + +syz_union2_struct { + f0 syz_union2 + f1 int8 +} [packed] + +# Arrays syz_test$array0(a0 ptr[in, syz_array_struct]) syz_test$array1(a0 ptr[in, syz_array_trailing]) @@ -77,7 +155,7 @@ syz_array_blob { f2 int16 } -# Length. +# Length syz_test$length0(a0 ptr[in, syz_length_int_struct]) syz_test$length1(a0 ptr[in, syz_length_const_struct]) @@ -178,7 +256,7 @@ syz_length_bytesize_struct { f5 bytesize8[f0, int8] } -# Big endian. +# Big endian syz_test$end0(a0 ptr[in, syz_end_int_struct]) syz_test$end1(a0 ptr[in, syz_end_var_struct]) @@ -199,18 +277,18 @@ syz_end_var_struct { f2 flags[syz_end_flags, int64be] } [packed] -# Vma type. +# Vma type syz_test$vma0(v0 vma, l0 len[v0], v1 vma[5], l1 len[v1], v2 vma[7:9], l2 len[v2]) -# Text type. +# Text type syz_test$text_x86_real(a0 ptr[in, text[x86_real]], a1 len[a0]) syz_test$text_x86_16(a0 ptr[in, text[x86_16]], a1 len[a0]) syz_test$text_x86_32(a0 ptr[in, text[x86_32]], a1 len[a0]) syz_test$text_x86_64(a0 ptr[in, text[x86_64]], a1 len[a0]) -# Regression tests. +# Regression tests syz_test$regression0(a0 ptr[inout, syz_regression0_struct]) @@ -218,11 +296,11 @@ syz_regression0_struct { f0 buffer[out] } -# Bitfields. +# Bitfields syz_bf_flags = 0, 1, 2 -syz_bf_struct { +syz_bf_struct0 { f0 flags[syz_bf_flags, int16:10] f1 int64 f2 const[0x42, int16:5] @@ -233,4 +311,16 @@ syz_bf_struct { f7 int8 } -syz_test$bf(a0 ptr[in, syz_bf_struct]) +syz_bf_struct1_internal { + f0 int32:10 + f1 int32:10 + f2 int32:10 +} + +syz_bf_struct1 { + f0 syz_bf_struct1_internal + f1 int8 +} + +syz_test$bf0(a0 ptr[in, syz_bf_struct0]) +syz_test$bf1(a0 ptr[in, syz_bf_struct1]) |
