Skip to content
Permalink
Browse files

pkg/compiler: support non-zero terminated filenames

Now file names become:

string[filename]

with a possibility of using other string features:

stringnoz[filename]
string[filename, CONST_SIZE]

and filename is left as type alias as it is commonly used:

type filename string[filename]
  • Loading branch information...
dvyukov committed Apr 2, 2018
1 parent 374050e commit 3e679c51c03ac13a5b4b601873689925eda3cc16
@@ -37,14 +37,11 @@ rest of the type-options are type-specific:
direction (in/out/inout)
"string": a zero-terminated memory buffer (no pointer indirection implied), type-options:
either a string value in quotes for constant strings (e.g. "foo"),
or a reference to string flags,
or a reference to string flags (special value `filename` produces file names),
optionally followed by a buffer size (string values will be padded with \x00 to that size)
"stringnoz": a non-zero-terminated memory buffer (no pointer indirection implied), type-options:
either a string value in quotes for constant strings (e.g. "foo"),
or a reference to string flags,
"filename": a file/link/dir name, no pointer indirection implied,
in most cases you want `ptr[in, filename]`, type-options:
static size (optional)
"fileoff": offset within a file
"len": length of another field (for array it is number of elements), type-options:
argname of the object
@@ -182,6 +179,8 @@ type bool16 int16[0:1]
type bool32 int32[0:1]
type bool64 int64[0:1]
type boolptr intptr[0:1]
type filename string[filename]
```

## Type Templates
@@ -2,7 +2,7 @@

#if defined(__i386__) || 0
#define GOARCH "386"
#define SYZ_REVISION "95c0c5827460dd0db116e00429bad9d3fe5778de"
#define SYZ_REVISION "32b0baef6733b7b01f968ccaf3b9966898e7454d"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
@@ -1693,7 +1693,7 @@ call_t syscalls[] = {

#if defined(__x86_64__) || 0
#define GOARCH "amd64"
#define SYZ_REVISION "14883eb285af454acfe15491ef6052eed4b8d77c"
#define SYZ_REVISION "8a54ebce3896b2b7a86248b86dc56d6072d33f4e"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
@@ -3436,7 +3436,7 @@ call_t syscalls[] = {

#if defined(__arm__) || 0
#define GOARCH "arm"
#define SYZ_REVISION "f64917dfdea0e40f17c49a8c12080a688ebb9a4d"
#define SYZ_REVISION "f044fd67eca13dc803c1f57973510ca9186a2df6"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
@@ -5124,7 +5124,7 @@ call_t syscalls[] = {

#if defined(__aarch64__) || 0
#define GOARCH "arm64"
#define SYZ_REVISION "6126db2a2079d8fe161c7d1e9c6179cf9a660b2d"
#define SYZ_REVISION "2b84001d08c857c19e8d97435de1bbe85336b0a3"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
@@ -6796,7 +6796,7 @@ call_t syscalls[] = {

#if defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__) || 0
#define GOARCH "ppc64le"
#define SYZ_REVISION "f4f6f2409448b0704d85d908ec0968994157ae6a"
#define SYZ_REVISION "c13af053f60f33816aba186c4a06e174af1bd018"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
@@ -110,6 +110,10 @@ func (comp *compiler) checkNames() {
comp.error(n.Pos, "string flags uses reserved name %v", name)
continue
}
if builtinStrFlags[name] != nil {
comp.error(n.Pos, "string flags conflicts with builtin flags", name)
continue
}
if prev := comp.strFlags[name]; prev != nil {
comp.error(n.Pos, "string flags %v redeclared, previously declared at %v",
name, prev.Pos)
@@ -64,8 +64,11 @@ func Compile(desc *ast.Description, consts map[string]uint64, target *targets.Ta
structNodes: make(map[*prog.StructDesc]*ast.Struct),
structVarlen: make(map[string]bool),
}
for name, typedef := range builtinTypedefs {
comp.typedefs[name] = typedef
for name, n := range builtinTypedefs {
comp.typedefs[name] = n
}
for name, n := range builtinStrFlags {
comp.strFlags[name] = n
}
comp.typecheck()
// The subsequent, more complex, checks expect basic validity of the tree,
@@ -261,26 +261,6 @@ var typeArgFlags = &typeArg{
},
}

var typeFilename = &typeDesc{
Names: []string{"filename"},
CantBeOpt: true,
OptArgs: 1,
Args: []namedArg{{"size", typeArgInt}},
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
return len(args) == 0
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = 0
if len(args) >= 1 {
base.TypeSize = args[0].Value
}
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferFilename,
}
},
}

var typeFileoff = &typeDesc{
Names: []string{"fileoff"},
CanBeArgRet: canBeArg,
@@ -478,6 +458,18 @@ var typeString = &typeDesc{
return comp.stringSize(t, args) == 0
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
if len(args) > 0 && args[0].Ident == "filename" {
base.TypeName = "filename"
base.TypeSize = 0
if len(args) >= 2 {
base.TypeSize = args[1].Value
}
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferFilename,
NoZ: t.Ident == stringnoz,
}
}
subkind := ""
if len(args) > 0 && args[0].Ident != "" {
subkind = args[0].Ident
@@ -729,6 +721,7 @@ var typeArgBase = namedArg{
var (
builtinTypes = make(map[string]*typeDesc)
builtinTypedefs = make(map[string]*ast.TypeDef)
builtinStrFlags = make(map[string]*ast.StrFlags)

// To avoid weird cases like ptr[in, in] and ptr[out, opt].
reservedName = map[string]bool{
@@ -745,6 +738,9 @@ type bool16 int16[0:1]
type bool32 int32[0:1]
type bool64 int64[0:1]
type boolptr intptr[0:1]
type filename string[filename]
filename = "", "."
`

func init() {
@@ -756,7 +752,6 @@ func init() {
typeLen,
typeConst,
typeFlags,
typeFilename,
typeFileoff,
typeVMA,
typeCsum,
@@ -780,6 +775,8 @@ func init() {
switch n := decl.(type) {
case *ast.TypeDef:
builtinTypedefs[n.Name.Name] = n
case *ast.StrFlags:
builtinStrFlags[n.Name.Name] = n
case *ast.NewLine:
default:
panic(fmt.Sprintf("unexpected node in builtins: %#v", n))
@@ -82,6 +82,13 @@ func (s *state) analyzeImpl(c *Call, resources bool) {
case BufferString:
s.strings[val] = true
case BufferFilename:
if len(val) < 3 {
// This is not our file, probalby one of specialFiles.
return
}
if val[len(val)-1] == 0 {
val = val[:len(val)-1]
}
s.files[val] = true
}
}
@@ -152,32 +152,42 @@ func (r *randGen) flags(vv []uint64) (v uint64) {

func (r *randGen) filename(s *state, typ *BufferType) string {
fn := r.filenameImpl(s)
if len(fn) != 0 && fn[len(fn)-1] == 0 {
panic(fmt.Sprintf("zero-terminated filename: %q", fn))
}
if !typ.Varlen() {
size := typ.Size()
if uint64(len(fn)) < size {
fn += string(make([]byte, size-uint64(len(fn))))
}
fn = fn[:size]
} else if !typ.NoZ {
fn += "\x00"
}
return fn
}

var specialFiles = []string{"", "/", "."}

func (r *randGen) filenameImpl(s *state) string {
dir := "."
if r.oneOf(2) && len(s.files) != 0 {
files := make([]string, 0, len(s.files))
for f := range s.files {
files = append(files, f)
}
dir = files[r.Intn(len(files))]
if len(dir) > 0 && dir[len(dir)-1] == 0 {
dir = dir[:len(dir)-1]
}
if r.oneOf(100) {
return specialFiles[r.Intn(len(specialFiles))]
}
if len(s.files) == 0 || r.oneOf(10) {
// Generate a new name.
dir := "."
if r.oneOf(2) && len(s.files) != 0 {
files := make([]string, 0, len(s.files))
for f := range s.files {
files = append(files, f)
}
dir = files[r.Intn(len(files))]
if len(dir) > 0 && dir[len(dir)-1] == 0 {
dir = dir[:len(dir)-1]
}
}
for i := 0; ; i++ {
f := fmt.Sprintf("%v/file%v\x00", dir, i)
f := fmt.Sprintf("%v/file%v", dir, i)
if !s.files[f] {
return f
}
@@ -259,12 +259,12 @@ const (
type BufferType struct {
TypeCommon
Kind BufferKind
RangeBegin uint64 // for BufferBlobRange kind, or static size for BufferFilename
RangeBegin uint64 // for BufferBlobRange kind
RangeEnd uint64 // for BufferBlobRange kind
Text TextKind // for BufferText
SubKind string
Values []string // possible values for BufferString kind
NoZ bool // non-zero terminated BufferString
NoZ bool // non-zero terminated BufferString/BufferFilename
}

func (t *BufferType) String() string {

0 comments on commit 3e679c5

Please sign in to comment.
You can’t perform that action at this time.