@@ -3,7 +3,7 @@ package kv
33import (
44 "bytes"
55 "encoding/binary"
6- "strconv "
6+ "io "
77
88 "github.com/cockroachdb/errors"
99)
@@ -14,6 +14,7 @@ const (
1414 txnIntentVersion byte = 1
1515 txnCommitVersion byte = 1
1616 txnRollbackVersion byte = 1
17+ txnReadChunkSize = 4096
1718)
1819
1920const txnLockFlagPrimary byte = 0x01
@@ -62,16 +63,9 @@ func DecodeTxnMeta(b []byte) (TxnMeta, error) {
6263 if primaryLen == 0 {
6364 return TxnMeta {PrimaryKey : nil , LockTTLms : ttl , CommitTS : commitTS }, nil
6465 }
65- plen , err := u64ToInt ( primaryLen )
66+ pk , err := readTxnField ( r , primaryLen , "txn meta: primary key truncated" )
6667 if err != nil {
67- return TxnMeta {}, errors .WithStack (err )
68- }
69- if plen > r .Len () {
70- return TxnMeta {}, errors .New ("txn meta: primary key truncated" )
71- }
72- pk := make ([]byte , plen )
73- if _ , err := r .Read (pk ); err != nil {
74- return TxnMeta {}, errors .WithStack (err )
68+ return TxnMeta {}, err
7569 }
7670 return TxnMeta {PrimaryKey : pk , LockTTLms : ttl , CommitTS : commitTS }, nil
7771}
@@ -125,16 +119,9 @@ func decodeTxnLock(b []byte) (txnLock, error) {
125119 if err := binary .Read (r , binary .BigEndian , & primaryLen ); err != nil {
126120 return txnLock {}, errors .WithStack (err )
127121 }
128- plen , err := u64ToInt ( primaryLen )
122+ primaryKey , err := readTxnField ( r , primaryLen , "txn lock: primary key truncated" )
129123 if err != nil {
130- return txnLock {}, errors .WithStack (err )
131- }
132- if plen > r .Len () {
133- return txnLock {}, errors .New ("txn lock: primary key truncated" )
134- }
135- primaryKey := make ([]byte , plen )
136- if _ , err := r .Read (primaryKey ); err != nil {
137- return txnLock {}, errors .WithStack (err )
124+ return txnLock {}, err
138125 }
139126 return txnLock {
140127 StartTS : startTS ,
@@ -188,19 +175,9 @@ func decodeTxnIntent(b []byte) (txnIntent, error) {
188175 if err := binary .Read (r , binary .BigEndian , & valLen ); err != nil {
189176 return txnIntent {}, errors .WithStack (err )
190177 }
191- vlen , err := u64ToInt ( valLen )
178+ val , err := readTxnField ( r , valLen , "txn intent: value truncated" )
192179 if err != nil {
193- return txnIntent {}, errors .WithStack (err )
194- }
195- if vlen > r .Len () {
196- return txnIntent {}, errors .New ("txn intent: value truncated" )
197- }
198- var val []byte
199- if vlen > 0 {
200- val = make ([]byte , vlen )
201- if _ , err := r .Read (val ); err != nil {
202- return txnIntent {}, errors .WithStack (err )
203- }
180+ return txnIntent {}, err
204181 }
205182 return txnIntent {StartTS : startTS , Op : op , Value : val }, nil
206183}
@@ -231,16 +208,39 @@ func encodeTxnRollbackRecord() []byte {
231208 return []byte {txnRollbackVersion }
232209}
233210
234- func u64ToInt (v uint64 ) (int , error ) {
235- if strconv .IntSize == 32 && v > uint64 (^ uint32 (0 )>> 1 ) {
236- return 0 , errors .New ("txn codec: length overflows int32" )
211+ func readTxnField (r * bytes.Reader , n uint64 , truncatedMessage string ) ([]byte , error ) {
212+ b , err := readTxnSizedBytes (r , n )
213+ if err == nil {
214+ return b , nil
237215 }
238- if strconv . IntSize == 64 && v > uint64 ( ^ uint ( 0 ) >> 1 ) {
239- return 0 , errors .New ("txn codec: length overflows int64" )
216+ if errors . Is ( err , io . EOF ) || errors . Is ( err , io . ErrUnexpectedEOF ) {
217+ return nil , errors .New (truncatedMessage )
240218 }
241- parsed , err := strconv .Atoi (strconv .FormatUint (v , 10 ))
242- if err != nil {
243- return 0 , errors .WithStack (err )
219+ return nil , errors .WithStack (err )
220+ }
221+
222+ func readTxnSizedBytes (r * bytes.Reader , n uint64 ) ([]byte , error ) {
223+ if n == 0 {
224+ return nil , nil
225+ }
226+
227+ var out []byte
228+ var chunkBuf [txnReadChunkSize ]byte
229+ remaining := n
230+ for remaining >= txnReadChunkSize {
231+ if _ , err := io .ReadFull (r , chunkBuf [:]); err != nil {
232+ return nil , errors .WithStack (err )
233+ }
234+ out = append (out , chunkBuf [:]... )
235+ remaining -= txnReadChunkSize
236+ }
237+ for remaining > 0 {
238+ b , err := r .ReadByte ()
239+ if err != nil {
240+ return nil , errors .WithStack (err )
241+ }
242+ out = append (out , b )
243+ remaining --
244244 }
245- return parsed , nil
245+ return out , nil
246246}
0 commit comments