Commit 2d7a1229 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 58f78727
...@@ -2836,7 +2836,7 @@ func (p *CheckReplicas) NEODecode(data []byte) (int, error) { ...@@ -2836,7 +2836,7 @@ func (p *CheckReplicas) NEODecode(data []byte) (int, error) {
l := binary.BigEndian.Uint32(data[0:]) l := binary.BigEndian.Uint32(data[0:])
data = data[4:] data = data[4:]
nread += 4 nread += 4
if uint32(len(data)) < l*8 { if uint32(len(data)) < 16+l*8 {
goto overflow goto overflow
} }
nread += l * 8 nread += l * 8
......
...@@ -211,6 +211,26 @@ func TestPktMarshal(t *testing.T) { ...@@ -211,6 +211,26 @@ func TestPktMarshal(t *testing.T) {
u64(8) + u64(7) + u64(1) + hex("00"), u64(8) + u64(7) + u64(1) + hex("00"),
}, },
// map[uint32]UUID + trailing ...
{&CheckReplicas{
PartitionDict: map[uint32]UUID{
1: 7,
2: 9,
7: 3,
4: 17,
},
MinTID: 23,
MaxTID: 128,
},
u32(4) +
u32(1) + u32(7) +
u32(2) + u32(9) +
u32(4) + u32(17) +
u32(7) + u32(3) +
u64(23) + u64(128),
},
// uint32, []uint32 // uint32, []uint32
{&PartitionCorrupted{7, []UUID{1,3,9,4}}, {&PartitionCorrupted{7, []UUID{1,3,9,4}},
u32(7) + u32(4) + u32(1) + u32(3) + u32(9) + u32(4), u32(7) + u32(4) + u32(1) + u32(3) + u32(9) + u32(4),
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
// +build ignore // +build ignore
/* /*
NEO. Protocol definition. Code generator NEO. Protocol module. Code generator
This program generates marshalling code for packet types defined in proto.go . This program generates marshalling code for packet types defined in proto.go .
For every type 3 methods are generated in accordance with NEOEncoder and For every type 3 methods are generated in accordance with NEOEncoder and
...@@ -27,7 +27,7 @@ List of packet types is obtained via searching through proto.go AST - looking ...@@ -27,7 +27,7 @@ List of packet types is obtained via searching through proto.go AST - looking
for appropriate struct declarations there. for appropriate struct declarations there.
Code generation for a type is organized via recursively walking through type's Code generation for a type is organized via recursively walking through type's
(sub-)elements and generating specialized code on leaf items (uintX, slices, (sub-)elements and generating specialized code on leaf items (intX, slices,
maps, ...). maps, ...).
Top-level generation driver is in generateCodecCode(). It accepts type Top-level generation driver is in generateCodecCode(). It accepts type
...@@ -153,7 +153,7 @@ import ( ...@@ -153,7 +153,7 @@ import (
} }
} }
// format & emit buffered code // format & emit generated code
code, err := format.Source(buf.Bytes()) code, err := format.Source(buf.Bytes())
if err != nil { if err != nil {
panic(err) // should not happen panic(err) // should not happen
...@@ -245,7 +245,7 @@ type CodeGenerator interface { ...@@ -245,7 +245,7 @@ type CodeGenerator interface {
// generate code to process a basic fixed type (not string) // generate code to process a basic fixed type (not string)
// userType is type actually used in source (for which typ is underlying), or nil // userType is type actually used in source (for which typ is underlying), or nil
// path is TODO // path is associated data member (to read from or write to)
genBasic(path string, typ *types.Basic, userType types.Type) genBasic(path string, typ *types.Basic, userType types.Type)
// generate code to process slice or map // generate code to process slice or map
...@@ -268,6 +268,7 @@ type CodeGenerator interface { ...@@ -268,6 +268,7 @@ type CodeGenerator interface {
// common part of codegenerators // common part of codegenerators
type commonCodeGen struct { type commonCodeGen struct {
buf Buffer // code is emitted here buf Buffer // code is emitted here
recvName string // receiver/type for top-level func recvName string // receiver/type for top-level func
typeName string // or empty typeName string // or empty
typ types.Type typ types.Type
...@@ -285,7 +286,7 @@ func (c *commonCodeGen) setFunc(recvName, typeName string, typ types.Type) { ...@@ -285,7 +286,7 @@ func (c *commonCodeGen) setFunc(recvName, typeName string, typ types.Type) {
c.typ = typ c.typ = typ
} }
// get variable for varname (and automatically mark var as used) // get variable for varname (and automatically mark this var as used)
func (c *commonCodeGen) var_(varname string) string { func (c *commonCodeGen) var_(varname string) string {
if c.varUsed == nil { if c.varUsed == nil {
c.varUsed = make(map[string]bool) c.varUsed = make(map[string]bool)
...@@ -294,7 +295,7 @@ func (c *commonCodeGen) var_(varname string) string { ...@@ -294,7 +295,7 @@ func (c *commonCodeGen) var_(varname string) string {
return varname return varname
} }
// information about symbolic size // symbolic size
// consists of numeric & symbolic expression parts // consists of numeric & symbolic expression parts
// size is num + expr1 + expr2 + ... // size is num + expr1 + expr2 + ...
type SymSize struct { type SymSize struct {
...@@ -337,35 +338,53 @@ func (s *SymSize) IsZero() bool { ...@@ -337,35 +338,53 @@ func (s *SymSize) IsZero() bool {
return s.num == 0 && len(s.exprv) == 0 return s.num == 0 && len(s.exprv) == 0
} }
// XXX just use `... = SymSize{}` ?
func (s *SymSize) Reset() { func (s *SymSize) Reset() {
*s = SymSize{} *s = SymSize{}
} }
// sizeCodeGen generates code to compute encoded size of a packet
// XXX naming ok? // XXX naming ok?
// XXX -> Gen_NEOEncodedLen ? // XXX -> Gen_NEOEncodedLen ?
// sizeCodeGen generates code to compute encoded size of a packet
//
// when type is recursively walked for every case symbolic size is added appropriately
// in case when it was needed to generate loops runtime accumulator variable is additionally used
// result is: symbolic size + (optionally) runtime accumulator
type sizeCodeGen struct { type sizeCodeGen struct {
commonCodeGen commonCodeGen
size SymSize // currently accumulated packet size size SymSize // currently accumulated packet size
} }
// encoder generates code to encode a packet // encoder generates code to encode a packet
//
// when type is recursively walked for every case code to update `data[n:]` is generated.
// no overflow checks are generated as by NEOEncoder interface provided data
// buffer should have at least NEOEncodedLen() length (the size computed by
// sizeCodeGen)
type encoder struct { type encoder struct {
commonCodeGen commonCodeGen
n int // current write position in data n int // current write position in data
} }
// decoder generates code to decode a packet // decoder generates code to decode a packet
//
// when type is recursively walked for every case code to decode next item from
// `data[n:]` is generated.
//
// overflow checks and, when convenient, nread updates are grouped and emitted
// so that they are performed in the beginning of greedy fixed-wire-size
// blocks.
//
// TODO more text?
type decoder struct { type decoder struct {
commonCodeGen commonCodeGen
// done buffer for generated code // done buffer for generated code
// current delayed overflow check will be inserted in between buf & bufDone // current delayed overflow check will be inserted in between bufDone & buf
bufDone Buffer bufDone Buffer
// current read position in data. n int // current read position in data.
n int
// size that will be checked for overflow at current overflow check point // size that will be checked for overflow at current overflow check point
overflowCheckSize SymSize overflowCheckSize SymSize
...@@ -439,9 +458,9 @@ func (d *decoder) resetPos() { ...@@ -439,9 +458,9 @@ func (d *decoder) resetPos() {
// //
// it is inserted // it is inserted
// - before reading variable sized item // - before reading variable sized item
// - XXX in loops ? // - in the beginning of loop inside XXX ok?
func (d *decoder) overflowCheckpoint() { func (d *decoder) overflowCheckpoint() {
//d.buf.emit("// overflow check point") //d.bufDone.emit("// overflow check point")
if !d.overflowCheckSize.IsZero() { if !d.overflowCheckSize.IsZero() {
d.bufDone.emit("if uint32(len(data)) < %v { goto overflow }", &d.overflowCheckSize) d.bufDone.emit("if uint32(len(data)) < %v { goto overflow }", &d.overflowCheckSize)
} }
...@@ -706,11 +725,6 @@ func (s *sizeCodeGen) genMap(path string, typ *types.Map, obj types.Object) { ...@@ -706,11 +725,6 @@ func (s *sizeCodeGen) genMap(path string, typ *types.Map, obj types.Object) {
curSize.AddExpr("len(%v) * %v", path, s.size.num) curSize.AddExpr("len(%v) * %v", path, s.size.num)
} }
s.size = curSize s.size = curSize
/*
s.emit("%v += %v", s.var_("size"), s.size)
s.emit("}")
*/
} }
func (e *encoder) genMap(path string, typ *types.Map, obj types.Object) { func (e *encoder) genMap(path string, typ *types.Map, obj types.Object) {
...@@ -746,6 +760,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -746,6 +760,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
keySize, keyFixed := typeSizeFixed(typ.Key()) keySize, keyFixed := typeSizeFixed(typ.Key())
elemSize, elemFixed := typeSizeFixed(typ.Elem()) elemSize, elemFixed := typeSizeFixed(typ.Elem())
itemFixed := keyFixed && elemFixed itemFixed := keyFixed && elemFixed
overflowCheckedCur := d.overflowChecked
if itemFixed { if itemFixed {
d.overflowCheckpoint() d.overflowCheckpoint()
d.overflowCheckSize.AddExpr("l * %v", keySize + elemSize) d.overflowCheckSize.AddExpr("l * %v", keySize + elemSize)
...@@ -788,10 +803,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -788,10 +803,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
d.emit("}") d.emit("}")
d.overflowCheckpoint() d.overflowChecked = overflowCheckedCur
d.resetPos()
//d.emit("%v= string(data[:l])", assignto)
d.emit("}") d.emit("}")
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment