# Copyright 2017 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

# Errors that happen during checking phase.

# Recursive resources.

resource r0[r0]			### recursive resource r0->r0
resource r1[r2]			### recursive resource r1->r2->r1
resource r2[r1]			### recursive resource r2->r1->r2
resource r3[int32]		### unused resource r3

foo$0(a0 ptr[out, r0], a1 ptr[out, r1], a2 ptr[out, r2])
foo$1(a0 r0, a1 r1, a2 r2)

# Recursive structs/unions.

sr1 {
	f1	sr1		### recursive declaration: sr1.f1 -> sr1 (mark some pointers as opt, or use variable-length arrays)
}

sr2 {
	f1	sr3
	f2	sr4
}

sr3 {
	f1	ptr[in, sr3]	### recursive declaration: sr3.f1 -> sr3 (mark some pointers as opt, or use variable-length arrays)
}

sr4 {
	f1	ptr[in, sr3]
	f2	array[ptr[in, sr5], 4]	### recursive declaration: sr4.f2 -> sr5.f2 -> sr6.f1 -> sr4 (mark some pointers as opt, or use variable-length arrays)
}

sr5 [
	f1	int32
	f2	sr6
]

sr6 {
	f1	sr4
}

sr7 {
	f1	ptr[in, sr7, opt]
}

type templ_sr[T] {
	f	T
}

sr8 {
	f	templ_sr[sr8]	### recursive declaration: sr8.f -> templ_sr[sr8].f -> sr8 (mark some pointers as opt, or use variable-length arrays)
}

sr9 {
	f	templ_sr[ptr[in, sr9]]	### recursive declaration: sr9.f -> templ_sr[ptr[in, sr9]].f -> sr9 (mark some pointers as opt, or use variable-length arrays)
}

sr10 {
	f0	array[sr10, 10]	### recursive declaration: sr10.f0 -> sr10 (mark some pointers as opt, or use variable-length arrays)
}

use_sr {
	u2	u2
	u3	u3
	s3	s3
	s4	s4
	s6	s6
	s8	s8
	sr1	sr1
	sr2	sr2
	sr5	sr5
	sr7	sr7
	sr8	sr8
	sr9	sr9
	sr10	sr10
	s400	s400
	s401	s401
	u400	u400
	u401	u401
	s402	s402
	s403	s403
} [packed]

foo$sr0(a ptr[in, use_sr])

# Len target tests.

foo$100(a int32, b len[a])
foo$101(a len[a])		### len target a refers to itself
foo$102(a ptr[in, len[a, int8]])	### len target a refers to itself
foo$103(a int32, b len[c])	### len target c does not exist in <foo$103>
foo$104(a len[parent])		### parent reached the call (foo$104)
foo$105(a ptr[in, int32], b ptr[in, array[len[a, int32]]])
foo$106(a int32, b ptr[in, csum[a, inet, int32]])
foo$107(a int32, b ptr[in, csum[c, inet, int32]])	### csum target c does not exist in <foo$107>

s1 {
	f1	len[s2, int32]	### len target s2 does not exist in s1
}

s2 {
	f1	s1
}

s3 {
	f1	int8
} [size[0]]			### size attribute has bad value 0, expect [1, 1<<20]

s4 {
	f1	int8
} [size[1000000000]]		### size attribute has bad value 1000000000, expect [1, 1<<20]

s6 {
	f1	int8
	f2	array[int8]
} [size[10]]			### varlen struct s6 has size attribute

s7 {
	f1	int32
	f2	u0
}

s8 {
	f1	int8
} [align[7]]			###  bad struct s8 alignment 7 (must be a sane power of 2)

u0 [
	f	len[f1, int32]	### len target f1 does not exist in u0
]

u1 [
	f1	ptr[in, array[int8]]
	f2	len[f1, int32]	### len target f1 does not exist in u1
]

u2 [
	f1	int8
] [size[0]]			### size attribute has bad value 0, expect [1, 1<<20]

u3 [
	f1	int8
] [varlen, size[8]]		### varlen union u3 has size attribute

foo$200(a ptr[in, s2])
foo$201(a ptr[in, s1])
foo$202(a ptr[in, s7])
foo$203(a u1)

foo$204(a ptr[in, slen1], b ptr[in, no_slen22])

slen1 {
	f0 len[parent, int32]
	f1 len[parent:f0, int32]
	f2 len[slen21:a, int32]		### len target a does not exist in slen2
	f3 len[f0:parent, int32]	### parent may only stay at the beginning (max 2 times)
	f4 len[slen2:f, int32]		### len path slen2 does not refer to a struct
	f5 len[slen22:f, int32]		### len path slen22 does not refer to a struct
	f6 len[syscall, int32]		### no argument name after syscall reference
	f7 len[syscall:c, int32]	### len target c does not exist in <foo$204>
	f8 offsetof[parent, int32]	### offsetof must refer to fields
	f9 offsetof[slen1, int32]	### offsetof must refer to fields
	f10 len[f0:syscall:b, int32]	### syscall can't be in the middle of path expressions
	f11 len[slen3:a, int32]		### len path slen3 does not refer to a struct
	slen2 ptr[in, array[slen2]]
	slen21 slen2
	slen3 slen3
	slen22 array[slen2]
}

slen2 {
	f	int32
	f1	slen3
	f2	len[parent:parent:slen22, int32] ### len target slen22 does not exist in no_slen22
}

slen3 [
	a int32
	b int32
	c len[parent:parent:parent:x, int32] ### parent may only stay at the beginning (max 2 times)
	d len[parent:a, int32] ### len target a does not exist in slen3
]

no_slen22 {
	# This one violates the parent:parent:slen22 chain.
	f slen2
}


# Resource ctor tests.

resource r100[int32]		### resource r100 can't be created (never mentioned as a syscall return value or output argument/field)
resource r101[int32]
resource r102[r101]
resource r103[r102]
resource r104[int8]
resource r105[int8]
resource r106[int8]		### resource r106 can't be created (never mentioned as a syscall return value or output argument/field)
resource r107[int8]		### resource r107 can't be created (never mentioned as a syscall return value or output argument/field)
resource r108[int8]		### resource r108 can't be created (never mentioned as a syscall return value or output argument/field)
resource r109[int8]		### resource r109 can't be created (never mentioned as a syscall return value or output argument/field)
resource r110[int8]
resource r111[int8]
resource r112[int8]		### resource r112 can't be created (never mentioned as a syscall return value or output argument/field)
resource r113[int8]
resource r114[int8]
resource r115[int8]		### resource r115 can't be created (never mentioned as a syscall return value or output argument/field)
resource r116[int8]		### resource r116 is never used as an input (such resources are not useful)
resource r117[int8]		### resource r117 is never used as an input (such resources are not useful)
resource r118[int8]		### resource r118 is never used as an input (such resources are not useful)
resource r119[int8]		### resource r119 is never used as an input (such resources are not useful)
resource r120[int8]		### resource r120 can't be created (never mentioned as a syscall return value or output argument/field)
resource r121[int8]		### resource r121 can't be created (never mentioned as a syscall return value or output argument/field)

foo$300(a0 r100, a1 r101, a2 r102, a3 r103, a4 r104, a5 r105, a6 r106, a7 r107, a8 r108)
foo$301(a0 r109, a1 r110, a2 r111, a3 r112, a4 r113, a5 r114, a6 r115, a7 r120)
foo$302(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104
foo$303(a ptr[in, s302], b ptr[in, s303], c ptr[in, s304], d ptr[out, s305], e ptr[inout, s306], f ptr[inout, s307], g ptr[in, s308], h ptr[out, s310])
foo$304(a ptr[out, r117], b ptr[in, s312], c ptr[in, s313]) r116
foo$305(a0 r121)
foo$306(a0 ptr[out, u315])

s300 {
	f1	ptr[inout, s301]
	f2	r106
}

s301 {
	f2	r105
}

s302 {
	f1	r108
}

s303 {
	f1	r109	(in)
}

# ptr to struct is in, field is out (valid, resource can be created)
s304 {
	f1	r110	(out)
}

# ptr to struct is out, field is in (error, resource can't be created)
s305 {
	f1	r111	(in)
}

# ptr to struct is inout, field is inout (valid, resource can be created)
s306 {
	f1	r111	(inout)
}

# ptr to struct is inout, fields are in (error) and out (valid)
s307 {
	f1	r112	(in)
	f2	r113	(out)
}

# recurse the out field inside two levels of in ptrs (valid, resource can be created)
s308 {
	f1	ptr[in, s309]
}

s309 {
	f1	ptr[out, r114]
}

# recurse the in field inside two levels of out ptrs (error, resource can't be created)
s310 {
	f1	ptr[out, s311]
}

s311 {
	f1	ptr[in, r115]
}

# ptr to struct is in, field is out (error, never used as an input)
s312 {
	f1	r118	(out)
}

# recurse the out field inside two levels of in ptrs (error, never used as an input)
s313 {
	f1	ptr[in, s314]
}

s314 {
	f1	r119	(out)
}

u315 [
	f1	r121
	f2	int32
]

# TODO: Two instances of the same resource might exist in the same structure as
# both in and out. How common is this and how to handle this?

# Varlen field tests.

s400 {
	f1	int32
	f2	array[int8]
}

s401 {
	f1	array[int8]
	f2	array[int8]
} [packed]

s402 {
	f1	array[int8]	### variable size field f1 in the middle of non-packed struct s402
	f2	int32
}

u400 [
	f1	array[int8]
	f2	array[int16]
] [varlen]

u401 [
	f1	filename	### variable size field f1 in non-varlen union u401
	f2	text[x86_64]	### variable size field f2 in non-varlen union u401
	f3	string		### variable size field f3 in non-varlen union u401
	f4	string["foo", 10]
	f5	string[sf400]
	f6	string[sf401]	### variable size field f6 in non-varlen union u401
	f7	s401		### variable size field f7 in non-varlen union u401
]

u402 [
	f1	int32
	f2	int32
] [varlen]

s403 {
	f1	u400		### variable size field f1 in the middle of non-packed struct s403
	f2	u402		### variable size field f2 in the middle of non-packed struct s403
	f3	int32
}

s404 {				### unused struct s404
	f1	int8
}

u404 [				### unused union u404
	f1	int8
]

sf400 = "foo", "bar", "baz"
sf401 = "a", "b", "cd"
sf402 = "a", "b"		### unused string flags sf402

# Const argument checks.

foo$500(a int32[3:2])		### bad int range [3:2]
foo$501(a ptr[in, int32[3:2]])	### bad int range [3:2]
foo$502(a ptr[in, string["foo", C1]])	### string value "foo\x00" exceeds buffer length 1
foo$503(a ptr[in, proc[1000, 1, int8]])	### values starting from 1000 overflow base type
foo$504(a ptr[in, proc[20, 10, int8]])	### values starting from 20 with step 10 overflow base type for 32 procs
foo$505(a proc[20, 0])		### proc per-process values must not be 0
foo$506(a ptr[in, array[int32, 0]])	### arrays of size 0 are not supported
foo$507(a ptr[in, array[int32, 0:0]])	### arrays of size 0 are not supported
foo$508(a ptr[in, string["foo", 3]])	### string value "foo\x00" exceeds buffer length 3
foo$509(a int8['b':'a'])		### bad int range [98:97]
foo$510(a type500)
foo$511(a int32[-10:-20])		### bad int range [18446744073709551606:18446744073709551596]
foo$512(a ptr[in, array[int8, -2:-1]])	### bad size range [18446744073709551614:18446744073709551615]
foo$513(a ptr[in, array[int8, -2:2]])	### bad size range [18446744073709551614:2]
foo$514(a vma[-2:2])			### bad size range [18446744073709551614:2]
foo$515(a ptr[in, proc[1, -10, int64]])	### values starting from 1 with step 18446744073709551606 overflow base type for 32 procs
foo$516(a ptr[in, intptr[0:2, 1]])	### bad int alignment 1
foo$517(a intptr[0:0xffffffff, 0])	### bad int alignment 0
foo$518(a int64[1:100, -1])		### int alignment 18446744073709551615 is too large for range [1:100]
foo$519(a int64[0:10, 512])		### int alignment 512 is too large for range [0:10]
foo$520(a int8[0:16, 0xffff])		### int alignment 65535 is too large for range [0:16]
foo$521(a int32[9:10, 8])		### int alignment 8 is too large for range [9:10]
foo$522(a int8[0:-1, 1000])		### int alignment 1000 is too large for range [0:255]
foo$523(a int8[0:256])			### int range [0:256] is too large for base type of size 8
foo$524(a int8[-1000:0])		### int range [18446744073709550616:0] is too large for base type of size 8
foo$525(a int8[-256:256])		### int range [18446744073709551360:256] is too large for base type of size 8
foo$526(a int8[-255:255])		### int range [18446744073709551361:255] is too large for base type of size 8
foo$527(a int16[-40000:40000])		### int range [18446744073709511616:40000] is too large for base type of size 16
foo$528(a ptr[in, s405])
foo$529(a ptr[in, string[`abcdde`, 3]])	### string value "\xab\xcd\xde\x00" exceeds buffer length 3
foo$530(a ptr[in, const[0x1ab, int8]])	### const val 0x1ab does not fit into 8 bits
foo$531(a ptr[in, const[0xffffffffffffffab, int8]])
foo$532(a ptr[in, const[0x7234567812345678, int64]])
foo$533(a ptr[in, const[0x12, int8:4]])	### const val 0x12 does not fit into 4 bits
foo$534(a ptr[in, flags[large_flags, int8]])	### large_flags U16_MAX=0xffff doesn't fit into 8 bits
foo$535(a int64[no])			### unknown flags no

large_flags = U8_MAX, U16_MAX

equal_flags_0 = 0, 0, 0, 0		### all equal_flags_0 values are equal 0
equal_flags_1 = 42, 42, 42, 42		### all equal_flags_1 values are equal 42
non_equal_flags = 0, 0, 0, 1

equal_flags_call(a flags[equal_flags_0], b flags[equal_flags_1], c flags[non_equal_flags])

type type500 proc[C1, 8, int8]	### values starting from 1 with step 8 overflow base type for 32 procs
type type501 int8		### unused type type501
type type502[C] const[C, int8]	### unused type type502

C2 = 0, 1, 2			### const C2 is already a flag
use_flags(a flags[C2])

s405 {
	f1	int16:8[-256:0]		### int range [18446744073709551360:0] is too large for base type of size 8
	f2	int16:8[0:256]		### int range [0:256] is too large for base type of size 8
	f3	int64:16[-65541:-10]	### int range [18446744073709486075:18446744073709551606] is too large for base type of size 16
	f4	int16:8[-255:0]		### int range [18446744073709551361:0] is too large for base type of size 8
}

# Field attributes.

foo$overlay(a ptr[in, struct$overlay0], b ptr[in, struct$out0])

struct$overlay0 {
	f0	int32
	f1	const[0, int32]	(out_overlay)	### const type must not be used as output
	f2	ptr[in, int32]			### ptr type must not be used as output
	f3	proc[0, 1, int32]		### proc type must not be used as output
	f4	bytesize[f1, int32]		### bytesize type must not be used as output
}

struct$out0 {
	f0	const[0, int32]	(out)		### const type must not be used as output
	f1	ptr[in, int32] (out)		### ptr type must not be used as output
	f2	proc[0, 1, int32] (out)		### proc type must not be used as output
	f3	bytesize[f1, int32] (out)	### bytesize type must not be used as output
}

struct_non_generatable {
	f0 ptr[in, array[compressed_image]]
}

union_non_minimizable [
	f0 struct_non_generatable
	f2 int32
]

foo$non_generatable(a compressed_image) (no_minimize)	### call foo$non_generatable refers to type compressed_image and so must be marked no_generate
foo$non_minimizable(a compressed_image) (no_generate)	### call foo$non_minimizable refers to type compressed_image and so must be marked no_minimize
foo$non_generatable_via_struct(a ptr[in, struct_non_generatable])	(no_minimize)	### call foo$non_generatable_via_struct refers to type compressed_image and so must be marked no_generate
foo$non_minimizable_via_union(a ptr[in, union_non_minimizable])	(no_generate)	### call foo$non_minimizable_via_union refers to type compressed_image and so must be marked no_minimize

resource for_fmt[int32]
foo$fmt_copyin(a ptr[in, fmt[dec, for_fmt]])
foo$fmt_copyout(a ptr[out, fmt[dec, for_fmt]])	### resource for_fmt cannot be created in fmt


define FLAG1 1
define FLAG2 2

some_nested_nested_flags {
	f4	int32
}

some_nested_flags {
	f1	int32
	f2	array[some_nested_nested_flags]
	f4	for_fmt
	f5	int32 (if[value[f1] == 0])
	f6	some_nested_nested_flags
} [packed]

conditional_fields {
	f1	int32
	f2      some_nested_flags (if[value[f1] & FLAG1])
	f3	some_nested_flags
	f4	int32	(if[value[f3:f1] != 0])
	f5	int32	(if[value[f3:f2:f4] != 0]) ### value path f2 does not refer to a struct
	f6	int32	(if[value[f3:f4] != 0]) ### f4 does not refer to a constant, an integer, or a flag
	f7	int32	(if[value[f3:some_field] != 0]) ### value target some_field does not exist in some_nested_flags
	f8	int32	(if[value[f3:f5] != 0]) ### f5 has conditions, so value path cannot reference it
	f9	int32	(if[value[parent:a] != 0]) ### value target a does not exist in conditional_fields
	f10	int32	(if[value[f3:f6] != 0]) ### f6 does not refer to a constant, an integer, or a flag
	f11	len[f2, int32] ### f2 has conditions, so len path cannot reference it
	f12	union_cond_fields
	f13	int32:8 (if[1]) ### bitfields may not have conditions
} [packed]

union_cond_fields [
	u1	int32 (if[value[parent:parent:f1] != 0])
	u2	int32 (if[value[parent:parent:unknown] != 0]) ### value target unknown does not exist in conditional_fields
	u3	int64
]

foo$conditional(a ptr[in, conditional_fields])

conditional_non_packed {
	f0	int64
	f1	conditional_non_packed_nested ### variable size field f1 in the middle of non-packed struct conditional_non_packed
	f2	int64
}

conditional_non_packed_nested {
	f3	int64 (if[value[parent:parent:f0]])
	f4	int32
} [packed]

foo$conditional2(a ptr[in, conditional_non_packed])

conditional_non_packed2 {
	f0	int64
	f1	int8	(if[value[f0] == 0]) ### variable size field f1 in the middle of non-packed struct conditional_non_packed2
	f2	int64
}

foo$conditional3(a ptr[in, conditional_non_packed2])
