Commit abb30701 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent f24296e3
...@@ -338,12 +338,55 @@ func (s *SymSize) IsZero() bool { ...@@ -338,12 +338,55 @@ 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{}
} }
// decoder overflow check state
type OverflowCheck struct {
// size to check for overflow
size SymSize
// whether overflow was already checked for current decodings
// (if yes, size updates will be ignored)
checked bool
// stack operated by {Push,Pop}Checked
checkedStk []bool
}
// push/pop checked state
func (o *OverflowCheck) PushChecked(checked bool) {
o.checkedStk = append(o.checkedStk, o.checked)
o.checked = checked
}
func (o *OverflowCheck) PopChecked() bool {
popret := o.checked
l := len(o.checkedStk)
o.checked = o.checkedStk[l-1]
o.checkedStk = o.checkedStk[:l-1]
return popret
}
// Add and AddExpr update .size accordingly, but only if overflow was not
// already marked as checked
func (o *OverflowCheck) Add(n int) {
if !o.checked {
o.size.Add(n)
}
}
func (o *OverflowCheck) AddExpr(format string, a ...interface{}) {
if !o.checked {
o.size.AddExpr(format, a...)
}
}
// XXX naming ok? // XXX naming ok?
// XXX -> Gen_NEOEncodedLen ? // XXX -> Gen_NEOEncodedLen ?
// sizeCodeGen generates code to compute encoded size of a packet // sizeCodeGen generates code to compute encoded size of a packet
...@@ -374,7 +417,7 @@ type encoder struct { ...@@ -374,7 +417,7 @@ type encoder struct {
// //
// overflow checks and, when convenient, nread updates are grouped and emitted // overflow checks and, when convenient, nread updates are grouped and emitted
// so that they are performed in the beginning of greedy fixed-wire-size // so that they are performed in the beginning of greedy fixed-wire-size
// blocks. // blocks - checking as much as possible in one go.
// //
// TODO more text? // TODO more text?
type decoder struct { type decoder struct {
...@@ -387,10 +430,7 @@ type decoder struct { ...@@ -387,10 +430,7 @@ type decoder struct {
n int // current read position in data. n int // current read position in data.
// 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 overflowCheck OverflowCheck
// whether overflow was already checked for current decodings
overflowChecked bool
} }
var _ CodeGenerator = (*sizeCodeGen)(nil) var _ CodeGenerator = (*sizeCodeGen)(nil)
...@@ -457,15 +497,15 @@ func (d *decoder) resetPos() { ...@@ -457,15 +497,15 @@ func (d *decoder) resetPos() {
// 2. mark current place as next overflow checkpoint to eventually emit // 2. mark current place as next overflow checkpoint to eventually emit
// //
// it is inserted // it is inserted
// - before reading variable sized item // - before reading a variable sized item
// - in the beginning of loop inside XXX ok? // - in the beginning of a loop inside
func (d *decoder) overflowCheckpoint() { func (d *decoder) overflowCheckpoint() {
//d.bufDone.emit("// overflow check point") //d.bufDone.emit("// overflow check point")
if !d.overflowCheckSize.IsZero() { if !d.overflowCheck.size.IsZero() {
d.bufDone.emit("if uint32(len(data)) < %v { goto overflow }", &d.overflowCheckSize) d.bufDone.emit("if uint32(len(data)) < %v { goto overflow }", &d.overflowCheck.size)
} }
d.overflowCheckSize.Reset() d.overflowCheck.size.Reset()
d.bufDone.Write(d.buf.Bytes()) d.bufDone.Write(d.buf.Bytes())
d.buf.Reset() d.buf.Reset()
...@@ -490,7 +530,7 @@ func (d *decoder) generatedCode() string { ...@@ -490,7 +530,7 @@ func (d *decoder) generatedCode() string {
} }
code.emit("return %v, nil", retexpr) code.emit("return %v, nil", retexpr)
// overflow is not used only for empty structs // `goto overflow` is not used only for empty structs
if (&types.StdSizes{8, 8}).Sizeof(d.typ) > 0 { if (&types.StdSizes{8, 8}).Sizeof(d.typ) > 0 {
code.emit("\noverflow:") code.emit("\noverflow:")
code.emit("return 0, ErrDecodeOverflow") code.emit("return 0, ErrDecodeOverflow")
...@@ -524,13 +564,9 @@ func (d *decoder) genBasic(assignto string, typ *types.Basic, userType types.Typ ...@@ -524,13 +564,9 @@ func (d *decoder) genBasic(assignto string, typ *types.Basic, userType types.Typ
dataptr := fmt.Sprintf("data[%v:]", d.n) dataptr := fmt.Sprintf("data[%v:]", d.n)
decoded := fmt.Sprintf(basic.decode, dataptr) decoded := fmt.Sprintf(basic.decode, dataptr)
d.n += basic.wireSize d.n += basic.wireSize
if !d.overflowChecked { d.overflowCheck.Add(basic.wireSize)
d.overflowCheckSize.Add(basic.wireSize)
}
if userType != nil && userType != typ { if userType != nil && userType != typ {
// userType is a named type over some basic, like // need to cast (like in encode case)
// type ClusterState int32
// -> need to cast
decoded = fmt.Sprintf("%v(%v)", typeName(userType), decoded) decoded = fmt.Sprintf("%v(%v)", typeName(userType), decoded)
} }
// NOTE no space before "=" - to be able to merge with ":" // NOTE no space before "=" - to be able to merge with ":"
...@@ -566,7 +602,7 @@ func (d *decoder) genSlice1(assignto string, typ types.Type) { ...@@ -566,7 +602,7 @@ func (d *decoder) genSlice1(assignto string, typ types.Type) {
d.n = 0 d.n = 0
d.overflowCheckpoint() d.overflowCheckpoint()
d.overflowCheckSize.AddExpr("l") d.overflowCheck.AddExpr("l")
switch t := typ.(type) { switch t := typ.(type) {
case *types.Basic: case *types.Basic:
...@@ -576,7 +612,7 @@ func (d *decoder) genSlice1(assignto string, typ types.Type) { ...@@ -576,7 +612,7 @@ func (d *decoder) genSlice1(assignto string, typ types.Type) {
d.emit("%v= string(data[:l])", assignto) d.emit("%v= string(data[:l])", assignto)
case *types.Slice: case *types.Slice:
// TODO not copy, but reference data from original // TODO eventually do not copy, but reference data from original
d.emit("%v= make(%v, l)", assignto, typeName(typ)) d.emit("%v= make(%v, l)", assignto, typeName(typ))
d.emit("copy(%v, data[:l])", assignto) d.emit("copy(%v, data[:l])", assignto)
...@@ -603,9 +639,7 @@ func (d *decoder) genArray1(assignto string, typ *types.Array) { ...@@ -603,9 +639,7 @@ func (d *decoder) genArray1(assignto string, typ *types.Array) {
typLen := int(typ.Len()) typLen := int(typ.Len())
d.emit("copy(%v[:], data[%v:%v])", assignto, d.n, d.n + typLen) d.emit("copy(%v[:], data[%v:%v])", assignto, d.n, d.n + typLen)
d.n += typLen d.n += typLen
if !d.overflowChecked { d.overflowCheck.Add(typLen)
d.overflowCheckSize.Add(typLen)
}
} }
...@@ -662,11 +696,11 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object) ...@@ -662,11 +696,11 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object)
// if size(item)==const - check overflow in one go // if size(item)==const - check overflow in one go
elemSize, elemFixed := typeSizeFixed(typ.Elem()) elemSize, elemFixed := typeSizeFixed(typ.Elem())
overflowCheckedCur := d.overflowChecked
if elemFixed { if elemFixed {
d.overflowCheckpoint() d.overflowCheckpoint()
d.overflowCheckSize.AddExpr("l * %v", elemSize) d.overflowCheck.AddExpr("l * %v", elemSize)
d.overflowChecked = true d.overflowCheck.PushChecked(true)
defer d.overflowCheck.PopChecked()
d.emit("%v += l * %v", d.var_("nread"), elemSize) d.emit("%v += l * %v", d.var_("nread"), elemSize)
} }
...@@ -691,8 +725,6 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object) ...@@ -691,8 +725,6 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object)
} }
d.emit("}") d.emit("}")
d.overflowChecked = overflowCheckedCur
d.emit("}") d.emit("}")
} }
...@@ -759,11 +791,11 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -759,11 +791,11 @@ 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.overflowCheck.AddExpr("l * %v", keySize + elemSize)
d.overflowChecked = true d.overflowCheck.PushChecked(true)
defer d.overflowCheck.PopChecked()
d.emit("%v += l * %v", d.var_("nread"), keySize + elemSize) d.emit("%v += l * %v", d.var_("nread"), keySize + elemSize)
} }
...@@ -800,8 +832,6 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -800,8 +832,6 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
} }
d.emit("}") d.emit("}")
d.overflowChecked = overflowCheckedCur
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