@@ -19,15 +19,13 @@ limitations under the License.
19
19
package shim
20
20
21
21
import (
22
- "bytes"
23
22
"errors"
24
23
"flag"
25
24
"fmt"
26
25
"io"
27
26
"os"
28
- "regexp"
29
- "strconv"
30
27
"strings"
28
+ "unicode/utf8"
31
29
32
30
"github.com/golang/protobuf/proto"
33
31
"github.com/golang/protobuf/ptypes/timestamp"
@@ -43,6 +41,11 @@ import (
43
41
// Logger for the shim package.
44
42
var chaincodeLogger = logging .MustGetLogger ("shim" )
45
43
44
+ const (
45
+ minUnicodeRuneValue = 0 //U+0000
46
+ maxUnicodeRuneValue = utf8 .MaxRune //U+10FFFF - maximum (and unallocated) code point
47
+ )
48
+
46
49
// ChaincodeStub is an object passed to chaincode for shim side handling of
47
50
// APIs.
48
51
type ChaincodeStub struct {
@@ -359,35 +362,52 @@ func (stub *ChaincodeStub) GetQueryResult(query string) (StateQueryIteratorInter
359
362
360
363
//CreateCompositeKey combines the given attributes to form a composite key.
361
364
func (stub * ChaincodeStub ) CreateCompositeKey (objectType string , attributes []string ) (string , error ) {
362
- return createCompositeKey (stub , objectType , attributes )
365
+ return createCompositeKey (objectType , attributes )
366
+ }
367
+
368
+ //SplitCompositeKey splits the key into attributes on which the composite key was formed.
369
+ func (stub * ChaincodeStub ) SplitCompositeKey (compositeKey string ) (string , []string , error ) {
370
+ return splitCompositeKey (compositeKey )
363
371
}
364
372
365
- func createCompositeKey (stub ChaincodeStubInterface , objectType string , attributes []string ) (string , error ) {
366
- var compositeKey bytes.Buffer
367
- replacer := strings .NewReplacer ("\x1E " , "\x1E \x1E " , "\x1F " , "\x1E \x1F " )
368
- compositeKey .WriteString (replacer .Replace (objectType ))
369
- for _ , attribute := range attributes {
370
- compositeKey .WriteString ("\x1F " + strconv .Itoa (len (attribute )) + "\x1F " )
371
- compositeKey .WriteString (replacer .Replace (attribute ))
373
+ func createCompositeKey (objectType string , attributes []string ) (string , error ) {
374
+ if err := validateCompositeKeyAttribute (objectType ); err != nil {
375
+ return "" , err
376
+ }
377
+ ck := objectType + string (minUnicodeRuneValue )
378
+ for _ , att := range attributes {
379
+ if err := validateCompositeKeyAttribute (att ); err != nil {
380
+ return "" , err
381
+ }
382
+ ck += att + string (minUnicodeRuneValue )
372
383
}
373
- return compositeKey . String () , nil
384
+ return ck , nil
374
385
}
375
386
376
- //SplitCompositeKey splits the key into attributes on which the composite key was formed.
377
- func (stub * ChaincodeStub ) SplitCompositeKey (compositeKey string ) (string , []string , error ) {
378
- return splitCompositeKey (stub , compositeKey )
387
+ func splitCompositeKey (compositeKey string ) (string , []string , error ) {
388
+ componentIndex := 0
389
+ components := []string {}
390
+ for i := 0 ; i < len (compositeKey ); i ++ {
391
+ if compositeKey [i ] == minUnicodeRuneValue {
392
+ components = append (components , compositeKey [componentIndex :i ])
393
+ componentIndex = i + 1
394
+ }
395
+ }
396
+ return components [0 ], components [1 :], nil
379
397
}
380
398
381
- func splitCompositeKey (stub ChaincodeStubInterface , compositeKey string ) (string , []string , error ) {
382
- re := regexp .MustCompile ("\x1F [0-9]+\x1F " )
383
- splittedKey := re .Split (compositeKey , - 1 )
384
- attributes := make ([]string , 0 )
385
- replacer := strings .NewReplacer ("\x1E \x1F " , "\x1F " , "\x1E \x1E " , "\x1E " )
386
- objectType := replacer .Replace (splittedKey [0 ])
387
- for _ , attr := range splittedKey [1 :] {
388
- attributes = append (attributes , replacer .Replace (attr ))
399
+ func validateCompositeKeyAttribute (str string ) error {
400
+ for index , runeValue := range str {
401
+ if ! utf8 .ValidRune (runeValue ) {
402
+ return fmt .Errorf ("Not a valid utf8 string. Contains rune [%d] starting at byte position [%d]" ,
403
+ runeValue , index )
404
+ }
405
+ if runeValue == minUnicodeRuneValue || runeValue == maxUnicodeRuneValue {
406
+ return fmt .Errorf (`Input contain unicode %#U starting at position [%d]. %#U and %#U are not allowed in the input attribute of a composite key` ,
407
+ runeValue , index , minUnicodeRuneValue , maxUnicodeRuneValue )
408
+ }
389
409
}
390
- return objectType , attributes , nil
410
+ return nil
391
411
}
392
412
393
413
//PartialCompositeKeyQuery function can be invoked by a chaincode to query the
@@ -402,7 +422,7 @@ func (stub *ChaincodeStub) PartialCompositeKeyQuery(objectType string, attribute
402
422
403
423
func partialCompositeKeyQuery (stub ChaincodeStubInterface , objectType string , attributes []string ) (StateQueryIteratorInterface , error ) {
404
424
partialCompositeKey , _ := stub .CreateCompositeKey (objectType , attributes )
405
- keysIter , err := stub .RangeQueryState (partialCompositeKey , partialCompositeKey + " \xFF " )
425
+ keysIter , err := stub .RangeQueryState (partialCompositeKey , partialCompositeKey + string ( maxUnicodeRuneValue ) )
406
426
if err != nil {
407
427
return nil , fmt .Errorf ("Error fetching rows: %s" , err )
408
428
}
0 commit comments