summaryrefslogtreecommitdiff
path: root/src/pkg/gob/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/gob/decode.go')
-rw-r--r--src/pkg/gob/decode.go82
1 files changed, 54 insertions, 28 deletions
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
index 4469089c4..9cd238736 100644
--- a/src/pkg/gob/decode.go
+++ b/src/pkg/gob/decode.go
@@ -18,6 +18,7 @@ import (
)
var (
+ errBadUint = os.ErrorString("gob: encoded unsigned integer out of range");
errRange = os.ErrorString("gob: internal error: field numbers out of bounds");
errNotStruct = os.ErrorString("gob: TODO: can only handle structs")
)
@@ -27,6 +28,14 @@ type decodeState struct {
b *bytes.Buffer;
err os.Error;
fieldnum int; // the last field number read.
+ buf []byte;
+}
+
+func newDecodeState(b *bytes.Buffer) *decodeState {
+ d := new(decodeState);
+ d.b = b;
+ d.buf = make([]byte, uint64Size);
+ return d;
}
func overflow(name string) os.ErrorString {
@@ -35,21 +44,34 @@ func overflow(name string) os.ErrorString {
// decodeUintReader reads an encoded unsigned integer from an io.Reader.
// Used only by the Decoder to read the message length.
-func decodeUintReader(r io.Reader, oneByte []byte) (x uint64, err os.Error) {
- for shift := uint(0);; shift += 7 {
- var n int;
- n, err = r.Read(oneByte);
- if err != nil {
- return 0, err
- }
- b := oneByte[0];
- x |= uint64(b) << shift;
- if b&0x80 != 0 {
- x &^= 0x80 << shift;
- break
+func decodeUintReader(r io.Reader, buf []byte) (x uint64, err os.Error) {
+ n1, err := r.Read(buf[0:1]);
+ if err != nil {
+ return
+ }
+ b := buf[0];
+ if b <= 0x7f {
+ return uint64(b), nil
+ }
+ nb := -int(int8(b));
+ if nb > uint64Size {
+ err = errBadUint;
+ return;
+ }
+ var n int;
+ n, err = io.ReadFull(r, buf[0:nb]);
+ if err != nil {
+ if err == os.EOF {
+ err = io.ErrUnexpectedEOF
}
+ return
+ }
+ // Could check that the high byte is zero but it's not worth it.
+ for i := 0; i < n; i++ {
+ x <<= 8;
+ x |= uint64(buf[i]);
}
- return x, nil;
+ return
}
// decodeUint reads an encoded unsigned integer from state.r.
@@ -59,17 +81,23 @@ func decodeUint(state *decodeState) (x uint64) {
if state.err != nil {
return
}
- for shift := uint(0);; shift += 7 {
- var b uint8;
- b, state.err = state.b.ReadByte();
- if state.err != nil {
- return 0
- }
- x |= uint64(b) << shift;
- if b&0x80 != 0 {
- x &^= 0x80 << shift;
- break
- }
+ var b uint8;
+ b, state.err = state.b.ReadByte();
+ if b <= 0x7f { // includes state.err != nil
+ return uint64(b)
+ }
+ nb := -int(int8(b));
+ if nb > uint64Size {
+ state.err = errBadUint;
+ return;
+ }
+ var n int;
+ n, state.err = state.b.Read(state.buf[0:nb]);
+ // Don't need to check error; it's safe to loop regardless.
+ // Could check that the high byte is zero but it's not worth it.
+ for i := 0; i < n; i++ {
+ x <<= 8;
+ x |= uint64(state.buf[i]);
}
return x;
}
@@ -338,8 +366,7 @@ func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer,
}
p = *(*uintptr)(up);
}
- state := new(decodeState);
- state.b = b;
+ state := newDecodeState(b);
state.fieldnum = -1;
basep := p;
for state.err == nil {
@@ -368,8 +395,7 @@ func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer,
}
func ignoreStruct(engine *decEngine, b *bytes.Buffer) os.Error {
- state := new(decodeState);
- state.b = b;
+ state := newDecodeState(b);
state.fieldnum = -1;
for state.err == nil {
delta := int(decodeUint(state));